Silently ignore invalid (already deleted) pastes
[phorkie.git] / src / phorkie / Database / Adapter / Elasticsearch / Search.php
1 <?php
2 namespace phorkie;
3
4 class Database_Adapter_Elasticsearch_Search implements Database_ISearch
5 {
6     protected static $sortMap = array(
7         'id' => array('id', 'asc'),
8         'crdate' => array('crdate', 'desc'),
9         'modate' => array('modate', 'desc'),
10         'tstamp' => array('tstamp', 'desc'),
11     );
12
13     public function __construct()
14     {
15         $this->searchInstance = $GLOBALS['phorkie']['cfg']['elasticsearch'];
16     }
17
18     /**
19      * List all repositories
20      *
21      * @param integer $page    Page of search results, starting with 0
22      * @param integer $perPage Number of results per page
23      * @param string  $sort    Sort order. Allowed values:
24      *                         - id     - repository id
25      *                         - crdate - creation date
26      *                         - modate - modification date
27      *                         - tstamp - last index date
28      *
29      * @return Search_Result Search result object
30      */
31     public function listAll($page = 0, $perPage = 10, $sort = 'id', $sortOrder = null)
32     {
33         list($sortField, $orderField) = $this->getSortField($sort, $sortOrder);
34         $r = new Database_Adapter_Elasticsearch_HTTPRequest(
35             $this->searchInstance . 'repo/_search',
36             \HTTP_Request2::METHOD_GET
37         );
38         $r->setBody(
39             json_encode(
40                 (object)array(
41                     'from'  => $page * $perPage,
42                     'size'  => $perPage,
43                     'sort'  => array(
44                         $sortField => $orderField
45                     ),
46                     'query' => (object)array(
47                         'match_all' => (object)array()
48                     ),
49                 )
50             )
51         );
52         $httpRes = $r->send();
53         $jRes = json_decode($httpRes->getBody());
54         if (isset($jRes->error)) {
55             throw new Exception(
56                 'Search exception: ' . $jRes->error, $jRes->status
57             );
58         }
59
60         $sres = new Search_Result();
61         $sres->results = $jRes->hits->total;
62         $sres->page    = $page;
63         $sres->perPage = $perPage;
64
65         foreach ($jRes->hits->hits as $hit) {
66             $r = new Repository();
67             try {
68                 $r->loadById($hit->_source->id);
69             } catch (Exception_NotFound $e) {
70                 continue;
71             }
72             $r->crdate = strtotime($hit->_source->crdate);
73             $r->modate = strtotime($hit->_source->modate);
74             $sres->repos[] = $r;
75         }
76
77         return $sres;
78     }
79
80
81     /**
82      * Search for a given term and return repositories that contain it
83      * in their description, file names or file content
84      *
85      * @param string  $term    Search term
86      * @param integer $page    Page of search results, starting with 0
87      * @param integer $perPage Number of results per page
88      *
89      * @return Search_Result Search result object
90      */
91     public function search($term, $page = 0, $perPage = 10)
92     {
93         $r = new Database_Adapter_Elasticsearch_HTTPRequest(
94             $this->searchInstance . 'repo/_search',
95             \HTTP_Request2::METHOD_GET
96         );
97         $r->setBody(
98             json_encode(
99                 (object)array(
100                     'from' => $page * $perPage,
101                     'size' => $perPage,
102                     'query' => (object)array(
103                         'bool' => (object)array(
104                             'should' => array(
105                                 (object)array(
106                                     'query_string' => (object)array(
107                                         'query' => $term,
108                                         'default_operator' => 'AND'
109                                     ),
110                                 ),
111                                 (object)array(
112                                     'has_child' => (object)array(
113                                         'type'         => 'file',
114                                         'query' => (object)array(
115                                             'query_string' => (object)array(
116                                                 'query' => $term,
117                                                 'default_operator' => 'AND'
118                                             )
119                                         )
120                                     )
121                                 )
122                             )
123                         )
124                     )
125                 )
126             )
127         );
128         $httpRes = $r->send();
129         $jRes = json_decode($httpRes->getBody());
130         if (isset($jRes->error)) {
131             throw new Exception(
132                 'Search exception: ' . $jRes->error, $jRes->status
133             );
134         }
135
136         $sres = new Search_Result();
137         $sres->results = $jRes->hits->total;
138         $sres->page    = $page;
139         $sres->perPage = $perPage;
140
141         foreach ($jRes->hits->hits as $hit) {
142             $r = new Repository();
143             //FIXME: error handling. what about deleted repos?
144             $r->loadById($hit->_source->id);
145             $sres->repos[] = $r;
146         }
147
148         return $sres;
149     }
150
151     protected function getSortField($sort, $sortOrder)
152     {
153         if (!isset(self::$sortMap[$sort])) {
154             throw new Exception('Invalid sort parameter: ' . $sort);
155         }
156         if ($sortOrder !== 'asc' && $sortOrder !== 'desc') {
157             throw new Exception('Invalid sortOrder parameter: ' . $sortOrder);
158         }
159
160         $data = self::$sortMap[$sort];
161         if ($sortOrder !== null) {
162             $data[1] = $sortOrder;
163         }
164         return $data;
165     }
166 }
167
168 ?>