29d1a2336384ae3145c45844f40ec961786c78f2
[core.git] / inc / classes / main / criteria / search / class_SearchCriteria.php
1 <?php
2 /**
3  * Search criteria for e.g. searching in databases. Do not use this class if
4  * you are looking for a ship or company, or what ever. Instead use this class
5  * for looking in storages like the database.
6  *
7  * @author              Roland Haeder <webmaster@shipsimu.org>
8  * @version             0.0.0
9  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2014 Core Developer Team
10  * @license             GNU GPL 3.0 or any newer version
11  * @link                http://www.shipsimu.org
12  *
13  * This program is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25  */
26 class SearchCriteria extends BaseCriteria implements LocalSearchCriteria {
27         /**
28          * Criteria to handle
29          */
30         private $criteria = array();
31
32         /**
33          * Limitation for the search
34          */
35         private $limit = 0;
36
37         /**
38          * Skip these entries before using them
39          */
40         private $skip = 0;
41
42         /**
43          * Protected constructor
44          *
45          * @return      void
46          */
47         protected function __construct () {
48                 // Call parent constructor
49                 parent::__construct(__CLASS__);
50         }
51
52         /**
53          * Create an instance of this class
54          *
55          * @return      $criteriaInstance       An instance of this criteria
56          */
57         public static final function createSearchCriteria () {
58                 // Get a new instance
59                 $criteriaInstance = new SearchCriteria();
60
61                 // Return this instance
62                 return $criteriaInstance;
63         }
64
65         /**
66          * Setter for limit
67          *
68          * @param       $limit  Search limit
69          * @return      void
70          * @todo        Find a nice casting here. (int) allows until and including 32766.
71          */
72         public final function setLimit ($limit) {
73                 $this->limit = $limit;
74         }
75
76         /**
77          * "Setter" for limit from a configuration entry
78          *
79          * @param       $configEntry    The configuration entry which hold a number as limit
80          * @return      void
81          */
82         public final function setConfiguredLimit ($configEntry) {
83                 // Get the limit from config entry and set it
84                 $limit = $this->getConfigInstance()->getConfigEntry($configEntry);
85                 $this->setLimit($limit);
86         }
87
88         /**
89          * Getter for limit
90          *
91          * @return      $limit  Search limit
92          */
93         public final function getLimit () {
94                 return $this->limit;
95         }
96
97         /**
98          * Setter for skip
99          *
100          * @param       $skip   Search skip
101          * @return      void
102          * @todo        Find a nice casting here. (int) allows until and including 32766.
103          */
104         public final function setSkip ($skip) {
105                 $this->skip = $skip;
106         }
107
108         /**
109          * Getter for skip
110          *
111          * @return      $skip   Search skip
112          */
113         public final function getSkip () {
114                 return $this->skip;
115         }
116
117         /**
118          * Checks whether the given key/value pair is matching with 'default' and one of 'choice' and
119          * never with in 'exclude'.
120          *
121          * @param       $key                    Key element to check
122          * @param       $value                  Value to check
123          * @param       $separator              Separator for "exploding" $value (default: ',')
124          * @return      $isMatching             Whether the key/value is matching or excluded
125          */
126         public function isCriteriaMatching ($key, $value, $separator = ',') {
127                 // $key/$value cannot be array/NULL/bool, value can be NULL but then NULL must be loocked for
128                 assert((!is_array($value)) && (!is_bool($value)) && (!is_array($key)) && (!is_null($key)) && (!is_bool($key)));
129
130                 // "Explode" value
131                 $valueArray = explode($separator, $value);
132
133                 // Debug message
134                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ' - ENTERED!');
135
136                 // Get 'default' search value
137                 $searchDefault = $this->getCriteriaElemnent($key);
138
139                 // Debug message
140                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault);
141
142                 // 'default' check
143                 $isMatching = (((($searchDefault !== FALSE) && ($searchDefault == $value)) || ((is_null($searchDefault)) && (is_null($value)))) || ($searchDefault === FALSE));
144
145                 // Debug message
146                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaElement(' . $key . ')[' . gettype($searchDefault) . ']=' . $searchDefault . ',isMatching=' . intval($isMatching));
147
148                 // Get 'choice' search value (can be NULL or $separator-separated string)
149                 $searchChoice = $this->getCriteriaChoiceElemnent($key);
150
151                 // May be FALSE or array
152                 assert(($searchChoice === FALSE) || (is_array($searchChoice)));
153
154                 // Debug message
155                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[' . gettype($searchChoice) . ']=' . print_r($searchChoice, TRUE));
156
157                 // 'choice' check
158                 if ((is_array($searchChoice)) && (count($valueArray) == 1)) {
159                         // $value is a single-search value, so use in_array()
160                         $isMatching = ((($isMatching === TRUE) || (($searchDefault === FALSE) && (!is_null($value)))) && (in_array($value, $searchChoice)));
161
162                         // Debug message
163                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - SINGLE-MATCH');
164                 } elseif ((is_array($searchChoice)) && (count($valueArray) > 1)) {
165                         // Debug message
166                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',isMatching=' . intval($isMatching));
167
168                         // $value is choice-search value, so check all entries
169                         $isMatching = (($isMatching === TRUE) || (($searchDefault === FALSE) && (!is_null($value))));
170                         $idx = 0;
171                         foreach ($valueArray as $idx => $match) {
172                                 // Debug message
173                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: match=' . $match . ',count(searchChoice)=' . count($searchChoice));
174
175                                 // Is it found? (one is okay)
176                                 $isMatching = (($isMatching === TRUE) && (in_array($match, $searchChoice)));
177
178                                 // Debug message
179                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: match=' . $match . ',isMatching=' . intval($isMatching));
180                         } // END - foreach
181
182                         // Debug message
183                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',valueArray()=' . count($valueArray) . ',idx=' . $idx . ',isMatching=' . intval($isMatching) . ' - CHOICE-MATCH');
184                 } else {
185                         // Choice-match is FALSE
186                         // Debug message
187                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - FALSE-MATCH');
188                 }
189
190                 // Debug message
191                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaChoiceElement(' . $key . ')[]=' . gettype($searchChoice) . ',isMatching=' . intval($isMatching));
192
193                 // Get 'exclude' search value
194                 $searchExclude = $this->getCriteriaExcludeElemnent($key);
195
196                 // Debug message
197                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: getCriteriaExcludeElement(' . $key . ')[' . gettype($searchExclude) . ']=' . $searchExclude);
198
199                 // 'exclude' check
200                 $isMatching = (
201                         (
202                                 (
203                                         $isMatching === TRUE
204                                 ) && (
205                                         $searchExclude === FALSE
206                                 )
207                         ) || (
208                                 (
209                                         (
210                                                 $isMatching === TRUE
211                                         ) && (
212                                                 $searchExclude !== FALSE
213                                         ) && (
214                                                 $searchExclude !== $value
215                                         )
216                                 )
217                         )
218                 );
219
220                 // Return result
221                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('SEARCH-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: key=' . $key . ',value[' . gettype($value) . ']=' . $value . ',isMatching=' . intval($isMatching) . ' - EXIT!');
222                 return $isMatching;
223         }
224 }
225
226 // [EOF]
227 ?>