_doc->isEnabledGoogleSearchEngine()) { $this->_showGoogleSearchResults(); return $this; } if (!$this->_doc->isEnabledDefaultSearchEngine()) { $this->_do404(); } if ($this->_restParams) { $alias = reset($this->_restParams); if (!in_array($alias, $this->_getProvidersAliases())) { $this->_do404(); return $this; } $this->_provider = $this->_getProviderByAlias($alias); $this->_action = 'providerList'; } else { $this->_action = 'partialList'; } return parent::exec(); } /** * @return mixed * @throws Qs_Exception */ protected function _getProviders() { if (null === $this->_providers) { $this->_providers = $this->getConfig('providers')->toArray(); if (!$this->_providers || !is_array($this->_providers)) { throw new Qs_Exception('Search data providers are not defined.'); } } return $this->_providers; } /** * @return array * @throws Qs_Exception */ protected function _getProvidersAliases() { if (null === $this->_providersAliases) { $this->_providersAliases = Qs_Array::fetchCol($this->_getProviders(), 'fullResultsAlias'); if (!$this->_providersAliases || !is_array($this->_providersAliases)) { throw new Qs_Exception('Search data providers declaration is wrong.'); } } return $this->_providersAliases; } /** * @param string $alias * @return array|bool */ protected function _getProviderByAlias($alias) { $providers = $this->_getProviders(); /** @var array $provider */ foreach ($providers as $provider) { if ($alias == $provider['fullResultsAlias']) { return $provider; } } return false; } /** * @return array */ protected function _getFilterFormOptions() { $options = [ 'method' => 'get', ]; return $options; } /** * @return View|Qs_ViewController */ protected function _addFilterItem() { if ($this->_hasFilter) { $form = $this->_getFilterForm(); if ($form->validate($form->getValidationValues())) { $this->_filter = $form->getValues(); } $this->_addFormItem($form); } return $this; } /** * @return array */ protected function _getListOptions() { $options = [ 'restParams' => $this->getRestParams(), 'templatePath' => $this->_getTemplatePath(), 'idItem' => $this->getIdItem(), ]; return $options; } /** * @param array $provider * @return Qs_Db_Obj * @throws Qs_Exception */ protected function _getProviderDataObj(array $provider) { if (class_exists($provider['dataObjClass'])) { /** @var Qs_Db_Obj $dataObj */ $dataObj = new $provider['dataObjClass']; $dataObj->addFilter(['query' => $this->_filter['q']]); if (!empty($provider['filterFields'])) { $dataObj->setFilterFields($provider['filterFields']); } } else { throw new Qs_Exception('Search provider with class ' . $provider['dataObjClass'] . ' is not found.'); } return $dataObj; } /** * @param array $provider * @return array */ protected function _getProviderTemplatePath(array $provider) { /** @var array $paths */ $paths = $this->_getTemplatePath(); $tplAlias = (isset($provider['templatePath']) && $provider['templatePath']) ? $provider['templatePath'] : $provider['fullResultsAlias']; $dir = preg_split('/[^a-zA-Z0-9]+/', $tplAlias); array_walk($dir, function (&$value, $key) { $value = ucfirst($value); }); $dir = implode('', $dir); $providerPath = reset($paths) . '/Provider/' . $dir; array_unshift($paths, $providerPath); return $paths; } /** * @param array $provider * @return Qs_ViewController_List */ protected function _getProviderList(array $provider) { $className = $this->_getClassName('List', substr($provider['dataObjClass'], 0, -3)); if (!class_exists($className)) { $className = 'Qs_ViewController_List'; } /** @var Qs_ViewController_List $list */ $list = new $className($this->_getListOptions()); $list->addUrlVariables(['q']); return $list; } protected function _isProviderPageEnable($provider) { $module = preg_replace( ['/Search\\\$/', '/Search_$/'], ['', ''], substr($provider['dataObjClass'], 0, -3), 1 ); $className = $this->_getClassName('View', $module); if (class_exists($className)) { $config = ($configOption = \Qs_Array::get($provider, 'configOption')) ? $configOption : null; $providerPageEnable = Qs_SiteMap::findFirst( null, ['type' => Qs_SiteMap::classToType($className)], $config, 'enabled'); if ('y' == $providerPageEnable) { return true; } } return false; } /** * @return View */ protected function _addPartialListItem() { $emptyResults = true; foreach ($this->_getProviders() as $provider) { if (false == $this->_isProviderPageEnable($provider)) { continue; } $dataObj = $this->_getProviderDataObj($provider); $list = $this->_getProviderList($provider); $list->setIpp(Qs_Array::get($provider, 'shortResultsLimit', $this->getConfig('shortResultsLimit'))); $list->setList($dataObj->setSelectOptions($list->getSelectOptions())->getSearchList($provider)); $list->setListSelect($dataObj->getListSelect()); $item = $list->toArray(); if (empty($item['list'])) { continue; } else { $emptyResults = false; } $item['provider'] = $provider; $item['baseUrl'] = constant('BASE_URL') . '/' . constant('CURRENT_PAGE_FINAL'); $item['filterString'] = http_build_query($this->_filter); $item['templatePath'] = $this->_getProviderTemplatePath($provider); $item['tpl'] = Qs_SiteMap::getTemplate('partialList.tpl', $item['templatePath']); $this->_doc->addItem($item); } if ($emptyResults) { $this->_addItem(['tpl' => $this->getTemplate('empty-results.tpl')]); } return $this; } /** * @return View * @throws Qs_Exception */ protected function _addProviderListItem() { if ($this->_provider) { $dataObj = $this->_getProviderDataObj($this->_provider); $list = $this->_getProviderList($this->_provider); $list->setList($dataObj->setSelectOptions($list->getSelectOptions())->getSearchList($this->_provider)); $list->setListSelect($dataObj->getListSelect()); $item = $list->toArray(); $item['baseUrl'] = constant('BASE_URL') . '/' . constant('CURRENT_PAGE_FINAL'); $item['filterString'] = http_build_query($this->_filter); $item['providerTitle'] = $this->_provider['providerTitle']; $item['partialSearchUrl'] = BASE_URL_LANGUAGE . '/' . CURRENT_PAGE_FINAL . '?' . http_build_query($this->_filter); $item['templatePath'] = $this->_getProviderTemplatePath($this->_provider); $item['tpl'] = Qs_SiteMap::getTemplate('providerList.tpl', $item['templatePath']); $this->_doc->addItem($item); } else { throw new Qs_Exception('Search data provider is not defined'); } return $this; } /** * @return View */ protected function _doPartialList() { $this->_addFilterItem(); if ('' != $this->_filter['q']) { $this->_addPartialListItem(); $this->_log(); } else { $this->_addItem(['tpl' => $this->getTemplate('empty-query.tpl')]); } return $this; } /** * @return View */ protected function _doProviderList() { $this->_addFilterItem(); if (!empty($this->_filter['q'])) { $this->_addProviderListItem(); $this->_log(); } else { $this->_addItem(['tpl' => $this->getTemplate('empty-query.tpl')]); } return $this; } /** * @return View|Qs_ViewController */ protected function _log() { if ($this->_hasLog && Qs_ViewController_Log::getEnabled()) { $this->_getLog()->write($this->_action, $this->_getObjectInfo()); } return $this; } protected function _getObjectInfo() { $info = []; $info['itemName'] = $this->getConfig('itemName'); $info['itemsName'] = $this->getConfig('itemsName'); if ($this->_provider) { $info = array_merge($info, $this->_provider); } $info = array_merge($info, $this->_filter); return $info; } protected function _getLog() { if (null === $this->_log) { parent::_getLog(); if (Qs_Array::get($this->_filter, 'q')) { $this->_log->addIgnoredControllers('App_Cms_View'); $this->_log->setAction('partialList', 'Made a site search. Keyword(s): "%q%"'); $this->_log->setAction('providerList', 'Made a site search. Category: %providerTitle%; Keyword(s): "%q%"'); } else { $this->_log->removeIgnoredController('App_Cms_View'); } } return $this->_log; } protected function _showGoogleSearchResults() { $item = [ 'searchEngineId' => App_Settings_Obj::get('googleSearchEngineId'), 'tpl' => $this->getTemplate('google-search-results.tpl'), ]; $this->_addItem($item); $this->_doc->addCriticalStylesheet('css/modules/google-search.css'); return $this; } }