render xsl
[phorkie.git] / src / phorkie / HtmlParser.php
1 <?php
2 namespace phorkie;
3
4 class HtmlParser
5 {
6     /**
7      * Contains error message when parse() failed
8      */
9     public $error;
10
11     /**
12      * Array with keys (URL title) and values (arrays of urls)
13      * Only supported URLs are included.
14      *
15      * @var array
16      */
17     protected $arGitUrls;
18
19
20
21     /**
22      * Extract git URLs from the given URL, eventually fetching
23      * HTML and extracting URLs from there.
24      *
25      * Sets $error and $arGitUrls class variables
26      *
27      * @param string $url  Git or HTTP URL
28      * @param string $html HTML content of $url
29      *
30      * @return boolean True when all went well, false in case of an error
31      * @uses   $error
32      * @uses   $arGitUrls
33      */
34     public function extractGitUrls($url, $html = null)
35     {
36         if ($url == '') {
37             $this->error = 'Empty fork URL';
38             return false;
39         }
40
41         $arUrl  = parse_url($url);
42         $scheme = isset($arUrl['scheme']) ? $arUrl['scheme'] : '';
43
44         if ($scheme == 'https' && isset($arUrl['host'])
45             && $arUrl['host'] == 'gist.github.com'
46         ) {
47             //FIXME: title
48             $this->arGitUrls[][] = 'git://gist.github.com/'
49                 . ltrim($arUrl['path'], '/') . '.git';
50             return true;
51         }
52
53         switch ($scheme) {
54         case 'git':
55             //clearly a git url
56             $this->arGitUrls = array(array($url));
57             return true;
58
59         case 'ssh':
60             //FIXME: maybe loosen this when we know how to skip the
61             //"do you trust this server" question of ssh
62             $this->error = 'ssh:// URLs are not supported';
63             return false;
64
65         case 'http':
66         case 'https':
67             return $this->extractUrlsFromHtml($url, $html);
68         }
69
70         $this->error = 'Unknown URLs scheme: ' . $scheme;
71         return false;
72     }
73
74     protected function extractUrlsFromHtml($url, $html = null)
75     {
76         //HTML is not necessarily well-formed, and Gitorious has many problems
77         // in this regard
78         //$sx = simplexml_load_file($url);
79
80         libxml_use_internal_errors(true);
81         if ($html === null) {
82             $sx = simplexml_import_dom(\DOMDocument::loadHTMLFile($url));
83         } else {
84             $sx = simplexml_import_dom(\DOMDocument::loadHTML($html));
85         }
86
87         $elems = $sx->xpath('//*[@rel="vcs-git"]');
88         $titles = $sx->xpath('/html/head/title');
89         $pageTitle = $this->cleanPageTitle((string) reset($titles));
90
91         $count = $anonymous = 0;
92         foreach ($elems as $elem) {
93             if (!isset($elem['href'])) {
94                 continue;
95             }
96             $str = (string)$elem;
97             if (isset($elem['title'])) {
98                 //<link href=".." rel="vcs-git" title="title" />
99                 $title = (string)$elem['title'];
100             } else if ($str != '') {
101                 //<a href=".." rel="vcs-git">title</a>
102                 $title = $str;
103             } else if ($pageTitle != '') {
104                 $title = $pageTitle;
105             } else {
106                 $title = 'Unnamed repository #' . ++$anonymous;
107             }
108             $url = (string)$elem['href'];
109             if ($this->isSupported($url)) {
110                 ++$count;
111                 $this->arGitUrls[$title][] = $url;
112             }
113         }
114
115         if ($count > 0) {
116             return true;
117         }
118
119         $this->error = 'No git:// clone URL found';
120         return false;
121     }
122
123     public function getGitUrls()
124     {
125         return $this->arGitUrls;
126     }
127
128     /**
129      * Remove application names from HTML page titles
130      *
131      * @param string $title HTML page title
132      *
133      * @return string Cleaned HTML page title
134      */
135     protected function cleanPageTitle($title)
136     {
137         $title = trim($title);
138         if (substr($title, -9) == '- phorkie') {
139             $title = trim(substr($title, 0, -9));
140         }
141
142         return $title;
143     }
144
145     public function isSupported($url)
146     {
147         $scheme = parse_url($url, PHP_URL_SCHEME);
148         return $scheme == 'git'
149             || $scheme == 'http' || $scheme == 'https';
150     }
151
152 }
153 ?>