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