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