implement request #13: simple remote forking works now
[phorkie.git] / src / phorkie / ForkRemote.php
1 <?php
2 namespace phorkie;
3
4 class ForkRemote
5 {
6     protected $url;
7
8     /**
9      * Array with keys (URL title) and values (arrays of urls)
10      * Only supported URLs are included.
11      *
12      * @var array
13      */
14     protected $arGitUrls;
15
16
17
18     public function __construct($url)
19     {
20         $this->url = $url;
21     }
22
23     public function parse()
24     {
25         $scheme = parse_url($this->url, PHP_URL_SCHEME);
26         switch ($scheme) {
27         case 'git':
28             //clearly a git url
29             $this->arGitUrls = array(array($this->url));
30             return true;
31
32         case 'ssh':
33             //FIXME: maybe loosen this when we know how to skip the
34             //"do you trust this server" question of ssh
35             $this->error = 'ssh:// URLs are not supported';
36             return false;
37
38         case 'http':
39         case 'https':
40             return $this->extractUrlsFromHtml($this->url);
41         }
42
43         $this->error = 'Unknown URLs scheme: ' . $scheme;
44         return false;
45     }
46
47     protected function extractUrlsFromHtml($url)
48     {
49         //HTML is not necessarily well-formed, and Gitorious has many problems
50         // in this regard
51         //$sx = simplexml_load_file($url);
52         libxml_use_internal_errors(true);
53         $sx = simplexml_import_dom(\DomDocument::loadHtmlFile($url));
54         $elems = $sx->xpath('//*[@rel="vcs-git"]');
55
56         $count = $anonymous = 0;
57         foreach ($elems as $elem) {
58             if (!isset($elem['href'])) {
59                 continue;
60             }
61             $str = (string)$elem;
62             if (isset($elem['title'])) {
63                 //<link href=".." rel="vcs-git" title="title" />
64                 $title = (string)$elem['title'];
65             } else if ($str != '') {
66                 //<a href=".." rel="vcs-git">title</a>
67                 $title = $str;
68             } else {
69                 $title = 'Unnamed repository #' . ++$anonymous;
70             }
71             $url = (string)$elem['href'];
72             if ($this->isSupported($url)) {
73                 ++$count;
74                 $this->arGitUrls[$title][] = $url;
75             }
76         }
77
78         return $count > 0;
79     }
80
81     /**
82      * Iterate through all git urls and return one if there is only
83      * one supported one.
84      *
85      * @return mixed Boolean false or string
86      */
87     public function getUniqueGitUrl()
88     {
89         $nFound = 0;
90         foreach ($this->arGitUrls as $title => $arUrls) {
91             foreach ($arUrls as $url) {
92                 $nFound++;
93                 $uniqueUrl = $url;
94             }
95         }
96
97         if ($nFound == 1) {
98             return $uniqueUrl;
99         }
100         return false;
101     }
102
103     public function getGitUrls()
104     {
105         return $this->arGitUrls;
106     }
107
108     public function isSupported($url)
109     {
110         return parse_url($url, PHP_URL_SCHEME) == 'git';
111     }
112 }
113
114 ?>