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