Total Complexity | 70 |
Total Lines | 725 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like tx_dlf_solr often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use tx_dlf_solr, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class tx_dlf_solr { |
||
22 | |||
23 | /** |
||
24 | * This holds the core name |
||
25 | * |
||
26 | * @var string |
||
27 | * @access protected |
||
28 | */ |
||
29 | protected $core = ''; |
||
30 | |||
31 | /** |
||
32 | * This holds the PID for the configuration |
||
33 | * |
||
34 | * @var integer |
||
35 | * @access protected |
||
36 | */ |
||
37 | protected $cPid = 0; |
||
38 | |||
39 | /** |
||
40 | * The extension key |
||
41 | * |
||
42 | * @var string |
||
43 | * @access public |
||
44 | */ |
||
45 | public static $extKey = 'dlf'; |
||
46 | |||
47 | /** |
||
48 | * This holds the max results |
||
49 | * |
||
50 | * @var integer |
||
51 | * @access protected |
||
52 | */ |
||
53 | protected $limit = 50000; |
||
54 | |||
55 | /** |
||
56 | * This holds the number of hits for last search |
||
57 | * |
||
58 | * @var integer |
||
59 | * @access protected |
||
60 | */ |
||
61 | protected $numberOfHits = 0; |
||
62 | |||
63 | /** |
||
64 | * This holds the additional query parameters |
||
65 | * |
||
66 | * @var array |
||
67 | * @access protected |
||
68 | */ |
||
69 | protected $params = array (); |
||
70 | |||
71 | /** |
||
72 | * Is the search instantiated successfully? |
||
73 | * |
||
74 | * @var boolean |
||
75 | * @access protected |
||
76 | */ |
||
77 | protected $ready = FALSE; |
||
78 | |||
79 | /** |
||
80 | * This holds the singleton search objects with their core as array key |
||
81 | * |
||
82 | * @var array(tx_dlf_solr) |
||
83 | * @access protected |
||
84 | */ |
||
85 | protected static $registry = array (); |
||
86 | |||
87 | /** |
||
88 | * This holds the Solr service object |
||
89 | * |
||
90 | * @var Apache_Solr_Service |
||
91 | * @access protected |
||
92 | */ |
||
93 | protected $service; |
||
94 | |||
95 | /** |
||
96 | * Escape all special characters in a query string |
||
97 | * |
||
98 | * @access public |
||
99 | * |
||
100 | * @param string $query: The query string |
||
101 | * |
||
102 | * @return string The escaped query string |
||
103 | */ |
||
104 | public static function escapeQuery($query) { |
||
105 | |||
106 | // Load class. |
||
107 | if (!class_exists('Apache_Solr_Service')) { |
||
108 | |||
109 | require_once(\TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName('EXT:'.self::$extKey.'/lib/SolrPhpClient/Apache/Solr/Service.php')); |
||
|
|||
110 | |||
111 | } |
||
112 | |||
113 | // Escape query phrase or term. |
||
114 | if (preg_match('/^".*"$/', $query)) { |
||
115 | |||
116 | return '"'.Apache_Solr_Service::escapePhrase(trim($query, '"')).'"'; |
||
117 | |||
118 | } else { |
||
119 | |||
120 | return Apache_Solr_Service::escape($query); |
||
121 | |||
122 | } |
||
123 | |||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Escape all special characters in a query string while retaining valid field queries |
||
128 | * |
||
129 | * @access public |
||
130 | * |
||
131 | * @param string $query: The query string |
||
132 | * @param integer $pid: The PID for the field configuration |
||
133 | * |
||
134 | * @return string The escaped query string |
||
135 | */ |
||
136 | public static function escapeQueryKeepField($query, $pid) { |
||
137 | |||
138 | // Is there a field query? |
||
139 | if (preg_match('/^[[:alnum:]]+_[tu][su]i:\(?.*\)?$/', $query)) { |
||
140 | |||
141 | // Get all indexed fields. |
||
142 | $fields = array (); |
||
143 | |||
144 | $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery( |
||
145 | 'tx_dlf_metadata.index_name,tx_dlf_metadata.index_tokenized,tx_dlf_metadata.index_stored', |
||
146 | 'tx_dlf_metadata', |
||
147 | 'tx_dlf_metadata.index_indexed=1 AND tx_dlf_metadata.pid='.intval($pid).' AND (tx_dlf_metadata.sys_language_uid IN (-1,0) OR tx_dlf_metadata.l18n_parent=0)'.tx_dlf_helper::whereClause('tx_dlf_metadata'), |
||
148 | '', |
||
149 | '', |
||
150 | '' |
||
151 | ); |
||
152 | |||
153 | if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) { |
||
154 | |||
155 | while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_row($result)) { |
||
156 | |||
157 | $fields[] = $resArray[0].'_'.($resArray[1] ? 't' : 'u').($resArray[2] ? 's' : 'u').'i'; |
||
158 | |||
159 | } |
||
160 | |||
161 | } |
||
162 | |||
163 | // Check if queried field is valid. |
||
164 | $splitQuery = explode(':', $query, 2); |
||
165 | |||
166 | if (in_array($splitQuery[0], $fields)) { |
||
167 | |||
168 | $query = $splitQuery[0].':('.self::escapeQuery(trim($splitQuery[1], '()')).')'; |
||
169 | |||
170 | } else { |
||
171 | |||
172 | $query = self::escapeQuery($query); |
||
173 | |||
174 | } |
||
175 | |||
176 | } elseif (!empty($query) && $query !== '*') { |
||
177 | |||
178 | // Don't escape plain asterisk search. |
||
179 | $query = self::escapeQuery($query); |
||
180 | |||
181 | } |
||
182 | |||
183 | return $query; |
||
184 | |||
185 | } |
||
186 | |||
187 | /** |
||
188 | * This is a singleton class, thus instances must be created by this method |
||
189 | * |
||
190 | * @access public |
||
191 | * |
||
192 | * @param mixed $core: Name or UID of the core to load |
||
193 | * |
||
194 | * @return tx_dlf_solr Instance of this class |
||
195 | */ |
||
196 | public static function getInstance($core) { |
||
197 | |||
198 | // Save parameter for logging purposes. |
||
199 | $_core = $core; |
||
200 | |||
201 | // Get core name if UID is given. |
||
202 | if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($core)) { |
||
203 | |||
204 | $core = tx_dlf_helper::getIndexName($core, 'tx_dlf_solrcores'); |
||
205 | |||
206 | } |
||
207 | |||
208 | // Check if core is set. |
||
209 | if (empty($core)) { |
||
210 | |||
211 | if (TYPO3_DLOG) { |
||
212 | |||
213 | \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_solr->getInstance('.$_core.')] Invalid core name "'.$core.'" for Apache Solr', self::$extKey, SYSLOG_SEVERITY_ERROR); |
||
214 | |||
215 | } |
||
216 | |||
217 | return; |
||
218 | |||
219 | } |
||
220 | |||
221 | // Check if there is an instance in the registry already. |
||
222 | if (is_object(self::$registry[$core]) && self::$registry[$core] instanceof self) { |
||
223 | |||
224 | // Return singleton instance if available. |
||
225 | return self::$registry[$core]; |
||
226 | |||
227 | } |
||
228 | |||
229 | // Create new instance... |
||
230 | $instance = new self($core); |
||
231 | |||
232 | // ...and save it to registry. |
||
233 | if ($instance->ready) { |
||
234 | |||
235 | self::$registry[$core] = $instance; |
||
236 | |||
237 | // Return new instance. |
||
238 | return $instance; |
||
239 | |||
240 | } else { |
||
241 | |||
242 | if (TYPO3_DLOG) { |
||
243 | |||
244 | \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_solr->getInstance('.$_core.')] Could not connect to Apache Solr server', self::$extKey, SYSLOG_SEVERITY_ERROR); |
||
245 | |||
246 | } |
||
247 | |||
248 | return; |
||
249 | |||
250 | } |
||
251 | |||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Returns the connection information a specific Solr core |
||
256 | * |
||
257 | * @access public |
||
258 | * |
||
259 | * @param string $core: Name of the core to load |
||
260 | * |
||
261 | * @return string The connection parameters for a specific Solr core |
||
262 | */ |
||
263 | public static function getSolrConnectionInfo($core = '') { |
||
264 | |||
265 | $solrInfo = array (); |
||
266 | |||
267 | // Extract extension configuration. |
||
268 | $conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]); |
||
269 | |||
270 | // Derive Solr host name. |
||
271 | $solrInfo['host'] = ($conf['solrHost'] ? $conf['solrHost'] : '127.0.0.1'); |
||
272 | |||
273 | // Prepend username and password to hostname. |
||
274 | if ($conf['solrUser'] && $conf['solrPass']) { |
||
275 | |||
276 | $solrInfo['host'] = $conf['solrUser'].':'.$conf['solrPass'].'@'.$solrInfo['host']; |
||
277 | |||
278 | } |
||
279 | |||
280 | // Set port if not set. |
||
281 | $solrInfo['port'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($conf['solrPort'], 1, 65535, 8180); |
||
282 | |||
283 | // Append core name to path. |
||
284 | $solrInfo['path'] = trim($conf['solrPath'], '/').'/'.$core; |
||
285 | |||
286 | return $solrInfo; |
||
287 | |||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Returns the request URL for a specific Solr core |
||
292 | * |
||
293 | * @access public |
||
294 | * |
||
295 | * @param string $core: Name of the core to load |
||
296 | * |
||
297 | * @return string The request URL for a specific Solr core |
||
298 | */ |
||
299 | public static function getSolrUrl($core = '') { |
||
300 | |||
301 | // Get Solr connection information. |
||
302 | $solrInfo = self::getSolrConnectionInfo($core); |
||
303 | |||
304 | // Return entire request URL. |
||
305 | return 'http://'.$solrInfo['host'].':'.$solrInfo['port'].'/'.$solrInfo['path']; |
||
306 | |||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Get next unused Solr core number |
||
311 | * |
||
312 | * @access public |
||
313 | * |
||
314 | * @param integer $start: Number to start with |
||
315 | * |
||
316 | * @return integer First unused core number found |
||
317 | */ |
||
318 | public static function solrGetCoreNumber($start = 0) { |
||
319 | |||
320 | $start = max(intval($start), 0); |
||
321 | |||
322 | // Check if core already exists. |
||
323 | if (self::getInstance('dlfCore'.$start) === NULL) { |
||
324 | |||
325 | return $start; |
||
326 | |||
327 | } else { |
||
328 | |||
329 | return self::solrGetCoreNumber($start + 1); |
||
330 | |||
331 | } |
||
332 | |||
333 | } |
||
334 | |||
335 | /** |
||
336 | * Processes a search request. |
||
337 | * |
||
338 | * @access public |
||
339 | * |
||
340 | * @param string $query: The search query |
||
341 | * |
||
342 | * @return tx_dlf_list The result list |
||
343 | */ |
||
344 | public function search($query = '') { |
||
530 | |||
531 | } |
||
532 | |||
533 | /** |
||
534 | * Processes a search request and returns the raw Apache Solr Documents. |
||
535 | * |
||
536 | * @access public |
||
537 | * |
||
538 | * @param string $query: The search query |
||
539 | * |
||
540 | * @return array The Apache Solr Documents that were fetched |
||
541 | */ |
||
542 | public function search_raw($query = '', $parameters = array ()) { |
||
543 | $solr_response = $this->service->search((string) $query, 0, $this->limit, array_merge($this->params, $parameters)); |
||
544 | |||
545 | $searchresult = array (); |
||
546 | |||
547 | foreach ($solr_response->response->docs as $doc) { |
||
548 | $searchresult[] = $doc; |
||
549 | } |
||
550 | |||
551 | return $searchresult; |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * This returns $this->limit via __get() |
||
556 | * |
||
557 | * @access protected |
||
558 | * |
||
559 | * @return integer The max number of results |
||
560 | */ |
||
561 | protected function _getLimit() { |
||
562 | |||
563 | return $this->limit; |
||
564 | |||
565 | } |
||
566 | |||
567 | /** |
||
568 | * This returns $this->numberOfHits via __get() |
||
569 | * |
||
570 | * @access protected |
||
571 | * |
||
572 | * @return integer Total number of hits for last search |
||
573 | */ |
||
574 | protected function _getNumberOfHits() { |
||
575 | |||
576 | return $this->numberOfHits; |
||
577 | |||
578 | } |
||
579 | |||
580 | /** |
||
581 | * This returns $this->ready via __get() |
||
582 | * |
||
583 | * @access protected |
||
584 | * |
||
585 | * @return boolean Is the search instantiated successfully? |
||
586 | */ |
||
587 | protected function _getReady() { |
||
588 | |||
589 | return $this->ready; |
||
590 | |||
591 | } |
||
592 | |||
593 | /** |
||
594 | * This returns $this->service via __get() |
||
595 | * |
||
596 | * @access protected |
||
597 | * |
||
598 | * @return Apache_Solr_Service Apache Solr service object |
||
599 | */ |
||
600 | protected function _getService() { |
||
603 | |||
604 | } |
||
605 | |||
606 | /** |
||
607 | * This sets $this->cPid via __set() |
||
608 | * |
||
609 | * @access protected |
||
610 | * |
||
611 | * @param integer $value: The new PID for the metadata definitions |
||
612 | * |
||
613 | * @return void |
||
614 | */ |
||
615 | protected function _setCPid($value) { |
||
616 | |||
617 | $this->cPid = max(intval($value), 0); |
||
618 | |||
619 | } |
||
620 | |||
621 | /** |
||
622 | * This sets $this->limit via __set() |
||
623 | * |
||
624 | * @access protected |
||
625 | * |
||
626 | * @param integer $value: The max number of results |
||
627 | * |
||
628 | * @return void |
||
629 | */ |
||
630 | protected function _setLimit($value) { |
||
631 | |||
632 | $this->limit = max(intval($value), 0); |
||
633 | |||
634 | } |
||
635 | |||
636 | /** |
||
637 | * This sets $this->params via __set() |
||
638 | * |
||
639 | * @access protected |
||
640 | * |
||
641 | * @param array $value: The query parameters |
||
642 | * |
||
643 | * @return void |
||
644 | */ |
||
645 | protected function _setParams(array $value) { |
||
646 | |||
647 | $this->params = $value; |
||
648 | |||
649 | } |
||
650 | |||
651 | /** |
||
652 | * This magic method is called each time an invisible property is referenced from the object |
||
653 | * |
||
654 | * @access public |
||
655 | * |
||
656 | * @param string $var: Name of variable to get |
||
657 | * |
||
658 | * @return mixed Value of $this->$var |
||
659 | */ |
||
660 | public function __get($var) { |
||
661 | |||
662 | $method = '_get'.ucfirst($var); |
||
663 | |||
664 | if (!property_exists($this, $var) || !method_exists($this, $method)) { |
||
665 | |||
666 | if (TYPO3_DLOG) { |
||
667 | |||
668 | \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_solr->__get('.$var.')] There is no getter function for property "'.$var.'"', self::$extKey, SYSLOG_SEVERITY_WARNING); |
||
669 | |||
670 | } |
||
671 | |||
672 | return; |
||
673 | |||
674 | } else { |
||
675 | |||
676 | return $this->$method(); |
||
677 | |||
678 | } |
||
679 | |||
680 | } |
||
681 | |||
682 | /** |
||
683 | * This magic method is called each time an invisible property is referenced from the object |
||
684 | * |
||
685 | * @access public |
||
686 | * |
||
687 | * @param string $var: Name of variable to set |
||
688 | * @param mixed $value: New value of variable |
||
689 | * |
||
690 | * @return void |
||
691 | */ |
||
692 | public function __set($var, $value) { |
||
693 | |||
694 | $method = '_set'.ucfirst($var); |
||
695 | |||
696 | if (!property_exists($this, $var) || !method_exists($this, $method)) { |
||
697 | |||
698 | if (TYPO3_DLOG) { |
||
699 | |||
700 | \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_solr->__set('.$var.', [data])] There is no setter function for property "'.$var.'"', self::$extKey, SYSLOG_SEVERITY_WARNING, $value); |
||
701 | |||
702 | } |
||
703 | |||
704 | } else { |
||
705 | |||
706 | $this->$method($value); |
||
707 | |||
708 | } |
||
709 | |||
710 | } |
||
711 | |||
712 | /** |
||
713 | * This is a singleton class, thus the constructor should be private/protected |
||
714 | * |
||
715 | * @access protected |
||
716 | * |
||
717 | * @param string $core: The name of the core to use |
||
718 | * |
||
719 | * @return void |
||
720 | */ |
||
721 | protected function __construct($core) { |
||
746 | |||
747 | } |
||
748 | |||
749 | } |
||
750 | |||
751 | } |
||
752 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths