a6fa8efef8fe9725722bf94bbd137671b73e3afe
[phinde.git] / src / phinde / LinkExtractor / Html.php
1 <?php
2 namespace phinde\LinkExtractor;
3
4 use phinde\LinkInfo;
5 use phinde\Helper;
6
7 class Html
8 {
9     public function extract(\HTTP_Request2_Response $res)
10     {
11         $url = $res->getEffectiveUrl();
12
13         $linkInfos = array();
14
15         //FIXME: mime type switch for cdata
16         $doc = new \DOMDocument();
17         //@ to hide parse warning messages in invalid html
18         @$doc->loadHTML($res->getBody());
19
20         //FIXME: extract base url from html
21         $base = new \Net_URL2($url);
22
23         $dx = new \DOMXPath($doc);
24
25         $meta = $dx->evaluate('/html/head/meta[@name="robots" and @content]')
26             ->item(0);
27         if ($meta) {
28             $robots = $meta->attributes->getNamedItem('content')->textContent;
29             foreach (explode(',', $robots) as $value) {
30                 if (trim($value) == 'nofollow') {
31                     //we shall not follow the links
32                     return array();
33                 }
34             }
35         }
36
37         $links = $dx->evaluate('//a');
38         //FIXME: link rel, img, video
39
40         $alreadySeen = array($url => true);
41
42         foreach ($links as $link) {
43             $linkTitle = Helper::sanitizeTitle($link->textContent);
44             $href = '';
45             foreach ($link->attributes as $attribute) {
46                 if ($attribute->name == 'href') {
47                     $href = $attribute->textContent;
48                 } else if ($attribute->name == 'rel') {
49                     foreach (explode(',', $attribute->textContent) as $value) {
50                         if (trim($value) == 'nofollow') {
51                             //we shall not follow this link
52                             continue 3;
53                         }
54                     }
55                 }
56             }
57             if ($href == '' || $href{0} == '#') {
58                 //link on this page
59                 continue;
60             }
61
62             $linkUrlObj = $base->resolve($href);
63             $linkUrlObj->setFragment(false);
64             $linkUrl    = (string) $linkUrlObj;
65             if (isset($alreadySeen[$linkUrl])) {
66                 continue;
67             }
68
69             switch ($linkUrlObj->getScheme()) {
70             case 'http':
71             case 'https':
72                 break;
73             default:
74                 continue 2;
75             }
76
77             //FIXME: check target type
78             $linkInfos[] = new LinkInfo(
79                $linkUrl, $linkTitle, $url
80             );
81             $alreadySeen[$linkUrl] = true;
82         }
83
84         return $linkInfos;
85     }
86 }
87 ?>