first version of comment extraction
[stapibas.git] / src / stapibas / Content / Extractor / Comment.php
1 <?php
2 namespace stapibas;
3
4 class Content_Extractor_Comment
5 {
6     public function __construct(Logger $log)
7     {
8         $this->log = $log;
9     }
10
11     /**
12      * Try to extract comment data from HTML
13      *
14      * @param object $doc HTML
15      * @param string $source URL this HTML has been loaded from
16      * @param string $target URL the reply should be to
17      *
18      * @return mixed NULL if nothing found, array if ok
19      */
20     public function extract(\DOMDocument $doc, $source, $target)
21     {
22         $xpath = $this->getXpath($doc);
23         $hentries = $xpath->query(
24             '//*[(' . $this->xpc('h-entry') . ' or ' . $this->xpc('hentry') . ') and '
25             . '//a['
26             . $this->xpc('u-in-reply-to') . ' and @href=' . $this->xpq($target)
27             . ']'
28             . ']'
29         );
30
31         if ($hentries->length == 0) {
32             return null;
33         }
34
35         $data = array(
36             'content' => null,
37             'title'   => null,
38         );
39         $hentry = $hentries->item(0);
40
41         $this->extractAuthorData($hentry, $xpath, $data, $doc);
42         $content = $this->getFirst(
43             './/*[' . $this->xpc('e-content') . ']', false, $hentry, $xpath
44         );
45         if ($content) {
46             $data['content'] = $this->innerHtml($content);
47         }
48         $data['title'] = $this->getFirst(
49             './/*[' . $this->xpc('p-name') . ']', false, $hentry, $xpath
50         );
51
52         return $data;
53     }
54
55     protected function extractAuthorData($hentry, $xpath, &$data, $d)
56     {
57         $data['author_name']  = null;
58         $data['author_image'] = null;
59         $data['author_url']   = null;
60
61         $authors = $xpath->evaluate(
62             './/*[' . $this->xpc('p-author') . ']'
63         );
64         if ($authors->length != 1) {
65             return false;
66         }
67
68         $author = $authors->item(0);
69
70         $data['author_name'] = $this->getFirst(
71             './/*[' . $this->xpc('p-name') . ' or ' . $this->xpc('fn') . ']',
72             null, $author, $xpath
73         );
74         $data['author_image'] = $this->getFirst(
75             './/*[' . $this->xpc('u-photo') . ']',
76             'src', $author, $xpath
77         );
78         $data['author_url'] = $this->getFirst(
79             './/*[' . $this->xpc('u-url') . ']',
80             'href', $author, $xpath
81         );
82     }
83
84     protected function getFirst($xpathExpr, $attrName, $elem, $xpath)
85     {
86         $items = $xpath->evaluate($xpathExpr, $elem);
87         if (!$items instanceof \DOMNodeList || $items->length == 0) {
88             return null;
89         }
90
91         if ($attrName === false) {
92             return $items->item(0);
93         } else if ($attrName == null) {
94             return $items->item(0)->nodeValue;
95         } else {
96             return $items->item(0)->attributes->getNamedItem($attrName)->nodeValue;
97         }
98     }
99
100     protected function innerHtml($element)
101     {
102         $innerHTML = '';
103         $children = $element->childNodes;
104         foreach ($children as $child) {
105             $tmp_dom = new \DOMDocument();
106             $tmp_dom->appendChild($tmp_dom->importNode($child, true));
107             $innerHTML .= rtrim($tmp_dom->saveHTML(), "\n");
108         }
109         return trim($innerHTML);
110     }
111
112     protected function getXpath($node)
113     {
114         $xpath = new \DOMXPath($node);
115         $xpath->registerNamespace('h', 'http://www.w3.org/1999/xhtml');
116         return $xpath;
117     }
118
119     protected function xpc($class)
120     {
121         return 'contains('
122             . 'concat(" ", normalize-space(@class), " "),'
123             . '" ' . $class . ' "'
124             . ')';
125     }
126
127     protected function xpq($str)
128     {
129         return '"' . htmlspecialchars($str, ENT_QUOTES) . '"';
130     }
131
132 }
133
134 ?>