c9ed748ad189f7f841cc2e6e96255e48f3d47b59
[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         $arUrl = parse_url($this->url);
26         $scheme = $arUrl['scheme'] ?: '';
27         if ($scheme == 'https' && isset($arUrl['host'])
28             && $arUrl['host'] == 'gist.github.com'
29         ) {
30             $scheme = 'git';
31             $this->url = 'git://gist.github.com/'. ltrim($arUrl['path'], '/') . '.git';
32         }
33
34         switch ($scheme) {
35         case 'git':
36             //clearly a git url
37             $this->arGitUrls = array(array($this->url));
38             return true;
39
40         case 'ssh':
41             //FIXME: maybe loosen this when we know how to skip the
42             //"do you trust this server" question of ssh
43             $this->error = 'ssh:// URLs are not supported';
44             return false;
45
46         case 'http':
47         case 'https':
48             return $this->extractUrlsFromHtml($this->url);
49         }
50
51         $this->error = 'Unknown URLs scheme: ' . $scheme;
52         return false;
53     }
54
55     protected function extractUrlsFromHtml($url)
56     {
57         //HTML is not necessarily well-formed, and Gitorious has many problems
58         // in this regard
59         //$sx = simplexml_load_file($url);
60         libxml_use_internal_errors(true);
61         $sx = simplexml_import_dom(\DomDocument::loadHtmlFile($url));
62         $elems = $sx->xpath('//*[@rel="vcs-git"]');
63
64         $count = $anonymous = 0;
65         foreach ($elems as $elem) {
66             if (!isset($elem['href'])) {
67                 continue;
68             }
69             $str = (string)$elem;
70             if (isset($elem['title'])) {
71                 //<link href=".." rel="vcs-git" title="title" />
72                 $title = (string)$elem['title'];
73             } else if ($str != '') {
74                 //<a href=".." rel="vcs-git">title</a>
75                 $title = $str;
76             } else {
77                 $title = 'Unnamed repository #' . ++$anonymous;
78             }
79             $url = (string)$elem['href'];
80             if ($this->isSupported($url)) {
81                 ++$count;
82                 $this->arGitUrls[$title][] = $url;
83             }
84         }
85
86         return $count > 0;
87     }
88
89     /**
90      * Iterate through all git urls and return one if there is only
91      * one supported one.
92      *
93      * @return mixed Boolean false or string
94      */
95     public function getUniqueGitUrl()
96     {
97         $nFound = 0;
98         foreach ($this->arGitUrls as $title => $arUrls) {
99             foreach ($arUrls as $url) {
100                 $nFound++;
101                 $uniqueUrl = $url;
102             }
103         }
104
105         if ($nFound == 1) {
106             return $uniqueUrl;
107         }
108         return false;
109     }
110
111     public function getGitUrls()
112     {
113         return $this->arGitUrls;
114     }
115
116     public function isSupported($url)
117     {
118         return parse_url($url, PHP_URL_SCHEME) == 'git';
119     }
120 }
121
122 ?>