Changes:
* added search model
@inheritdoc
357577
public function generate()
    {
        $files = [];
        $relations = $this->generateRelations();
        $db = $this->getDbConnection();
        foreach ($this->getTableNames() as $tableName) {
            // model :
            $modelClassName = $this->generateClassName($tableName);
            $queryClassName = ($this->generateQuery) ? $this->generateQueryClassName($modelClassName) : false;
            $searchClassName = ($this->generateQuery) ? $this->generateSearchClassName($modelClassName) : false;
            $tableSchema = $db->getTableSchema($tableName);
            $params = [
                'tableName' => $tableName,
                'className' => $modelClassName,
                'queryClassName' => $queryClassName,
                'tableSchema' => $tableSchema,
                'labels' => $this->generateLabels($tableSchema),
                'rules' => $this->generateRules($tableSchema, false, false),
                'filterRules' => $this->generateRules($tableSchema, false, true),
                'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [],
                'behaviors' => $this->generateBehaviors($tableSchema),
            ];
            $files[] = new CodeFile(
                Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $modelClassName . '.php',
                $this->render('model.php', $params)
            );

            if ($queryClassName) {
                $params = [
                    'className' => $queryClassName,
                    'modelClassName' => $modelClassName,
                ];
                $files[] = new CodeFile(
                    Yii::getAlias('@' . str_replace('\\', '/', $this->queryNs)) . '/' . $queryClassName . '.php',
                    $this->render('query.php', $params)
                );
            }

            if ($searchClassName) {
                $params = [
                    'className' => $searchClassName,
                    'modelClassName' => $modelClassName,
                    'queryClassName' => $queryClassName ? $queryClassName : 'ActiveQuery',
                    'labels' => $this->generateLabels($tableSchema),
                    'rules' => $this->generateRules($tableSchema, true, false),
                    'filterRules' => $this->generateRules($tableSchema, true, true),
                    'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [],
                ];
                $files[] = new CodeFile(
                    Yii::getAlias('@' . str_replace('\\', '/', $this->searchNs)) . '/' . $searchClassName . '.php',
                    $this->render('search.php', $params)
                );
            }
        }

        return $files;
    }
1182157
public function search(SearchRequest $request)
    {
        $this->eventDispatcher->dispatch(ONGRFilterManagerEvents::PRE_SEARCH, new PreSearchEvent($request));

        $search = $this->container->buildSearch($request);

        /** @var FilterInterface $filter */
        foreach ($this->container->all() as $name => $filter) {
            $relatedSearch = new Search();

            if ($filter->isRelated()) {
                // We simply exclude not related filters and current filter itself.
                $relatedFilters = $this->container->getFiltersByRelation(
                    new AndRelation([$filter->getSearchRelation(), new ExcludeRelation([$name])])
                );
                $relatedSearch = $this->container->buildSearch($request, $relatedFilters);
            }

            $this->eventDispatcher->dispatch(
                ONGRFilterManagerEvents::PRE_PROCESS_SEARCH,
                new PreProcessSearchEvent($request->get($name), $relatedSearch)
            );

            $filter->preProcessSearch(
                $search,
                $relatedSearch,
                $request->get($name)
            );
        }

        $result = $this->repository->findDocuments($search);
        $this->eventDispatcher->dispatch(ONGRFilterManagerEvents::SEARCH_RESPONSE, new SearchResponseEvent($result));

        return new SearchResponse(
            $this->getFiltersViewData($result, $request),
            $result,
            $this->composeUrlParameters($request),
            $this->serializer
        );
    }
1369102
protected function addAllFilter($search)
    {
        $this->builder = $this->builder->where(
            function ($query) use ($search) {
                foreach ($this->columns as $column) {
                    $query->orWhere(
                        new raw($this->getRawColumnQuery($column)),
                        'like',
                        '%' . $search . '%'
                    );
                }
            }
        );
    }
819390
public function search() {
		$this->SearchFilter->search();
		$pageTitle = __d('cake_search_info', 'Search information');
		$breadCrumbs = $this->Search->getBreadcrumbInfo();
		$breadCrumbs[] = __d('cake_search_info', 'Results of search');
		$this->set(compact('pageTitle', 'breadCrumbs'));
	}
1240777
public function do_search()
    {
        $query = (string) $this->request->request('query');

        $ipl = new PageList();
        $aksearch = false;
        $akIDs = $this->request->request('akID');
        if (is_array($akIDs)) {
            foreach ($akIDs as $akID => $req) {
                $fak = CollectionAttributeKey::getByID($akID);
                if (is_object($fak)) {
                    $type = $fak->getAttributeType();
                    $cnt = $type->getController();
                    $cnt->setAttributeKey($fak);
                    $cnt->searchForm($ipl);
                    $aksearch = true;
                }
            }
        }

        if ($this->request->request('month') !== null && $this->request->request('year') !== null) {
            $year = @(int) ($this->request->request('year'));
            $month = abs(@(int) ($this->request->request('month')));
            if (strlen(abs($year)) < 4) {
                $year = (($year < 0) ? '-' : '') . str_pad(abs($year), 4, '0', STR_PAD_LEFT);
            }
            if ($month < 12) {
                $month = str_pad($month, 2, '0', STR_PAD_LEFT);
            }
            $daysInMonth = date('t', strtotime("$year-$month-01"));
            $dh = Core::make('helper/date');
            /* @var $dh \Concrete\Core\Localization\Service\Date */
            $start = $dh->toDB("$year-$month-01 00:00:00", 'user');
            $end = $dh->toDB("$year-$month-$daysInMonth 23:59:59", 'user');
            $ipl->filterByPublicDate($start, '>=');
            $ipl->filterByPublicDate($end, '<=');
            $aksearch = true;
        }

        if ($query === '' && $aksearch === false) {
            return false;
        }

        if ($query !== '') {
            $ipl->filterByKeywords($query);
        }

        $search_paths = $this->request->request('search_paths');
        if (is_array($search_paths)) {
            foreach ($search_paths as $path) {
                if ($path === '') {
                    continue;
                }
                $ipl->filterByPath($path);
            }
        } elseif ($this->baseSearchPath != '') {
            $ipl->filterByPath($this->baseSearchPath);
        }

        $cak = CollectionKey::getByHandle('exclude_search_index');
        if (is_object($cak)) {
            $ipl->filterByExcludeSearchIndex(false);
        }

        $pagination = $ipl->getPagination();
        $results = $pagination->getCurrentPageResults();

        $this->set('query', $query);
        $this->set('results', $results);
        $this->set('do_search', true);
        $this->set('searchList', $ipl);
        $this->set('pagination', $pagination);
    }
778686
public function upgradeDatabase()
    {
        $this->refreshEntities([
            'Concrete\Core\Entity\Attribute\Key\Settings\BooleanSettings',
        ]);
        $em = $this->connection->getEntityManager();
        $ak = CollectionKey::getByHandle('exclude_nav');
        if ($ak) {
            $settings = $ak->getController()->getAttributeKeySettings();
            if ($settings) {
                $settings->setCheckboxLabel('Exclude Page from Navigation');
                $settings->setAttributeKey($ak);
                $em->persist($settings);
            }
        }
        $ak = CollectionKey::getByHandle('exclude_page_list');
        if ($ak) {
            $settings = $ak->getController()->getAttributeKeySettings();
            if ($settings) {
                $settings->setCheckboxLabel('Exclude Page from Page List Blocks');
                $settings->setAttributeKey($ak);
                $em->persist($settings);
            }
        }
        $ak = CollectionKey::getByHandle('is_featured');
        if ($ak) {
            $settings = $ak->getController()->getAttributeKeySettings();
            if ($settings) {
                $settings->setCheckboxLabel('Feature this Page');
                $settings->setAttributeKey($ak);
                $em->persist($settings);
            }
        }
        $em->flush();
    }
1313204
void updateSearchResults(boolean selectFirstMatch)
    {
        clearHighlights();
        searchPanel.setMessage("");
        
        String query = searchPanel.getQuery();

        if (query.isEmpty())
        {
            handleMatch(null);
            return;
        }
        
        String text = getDocumentText();
        boolean ignoreCase = !searchPanel.isCaseSensitive();
        List<Point> appearances = 
            JTextComponents.find(text, query, ignoreCase);
        addHighlights(appearances, highlightColor);

        int caretPosition = textComponent.getCaretPosition();
        Point match = JTextComponents.findNext(
            text, query, caretPosition, ignoreCase);
        if (match == null)
        {
            match = JTextComponents.findNext(
                text, query, 0, ignoreCase);
        }
        if (selectFirstMatch)
        {
            handleMatch(match);
        }
        else
        {
            handleMatch(null);
        }

        if (appearances.isEmpty())
        {
            searchPanel.setMessage("Not found");
        }
        else
        {
            searchPanel.setMessage(
                "Found " + appearances.size() + " times");
        }
    }
447444
protected function search(QueryBuilder $qb, string $search): void
    {
        $query = $this->queryDefinition;
        $node = $this->objectDefinition;

        $em = $this->getManager();
        $metadata = $em->getClassMetadata($this->entity);

        $node->getFields();
        $columns = [];
        $searchFields = FieldOptionsHelper::normalize($query->getMeta('pagination')['search_fields'] ?? ['*']);
        foreach ($node->getFields() as $field) {
            if (!FieldOptionsHelper::isEnabled($searchFields, $field->getName())) {
                continue;
            }

            $config = FieldOptionsHelper::getConfig($searchFields, $field->getName(), null);
            $searchColumn = null;
            if ($metadata->hasField($field->getName())) {
                $searchColumn = $field->getName();
            }

            if ($metadata->hasField($field->getOriginName())) {
                $searchColumn = $field->getOriginName();
            }

            if ($searchColumn) {
                switch ($metadata->getFieldMapping($searchColumn)['type']) {
                    case Type::STRING:
                    case Type::TEXT:
                        $columns[$searchColumn] = $config ?? 'partial';
                        break;
                    case Type::INTEGER:
                    case Type::BIGINT:
                    case Type::FLOAT:
                    case Type::DECIMAL:
                    case Type::SMALLINT:
                        $columns[$searchColumn] = $config ?? 'exact';
                        break;
                }
            }
        }

        foreach ($searchFields as $field => $mode) {
            if (\is_int($field)) {
                $field = $mode;
                $mode = 'exact';
            }

            if ('*' === $field) {
                continue;
            }
            $columns[$field] = $mode;
        }


        if (\count($columns) > 0) {
            $joins = [];
            $orx = new Orx();
            foreach ($columns as $column => $mode) {
                $alias = $qb->getRootAliases()[0];
                if (strpos($column, '.') !== false) {
                    [$child, $column] = explode('.', $column);
                    $parentAlias = $alias;
                    $alias = 'searchJoin'.ucfirst($child);
                    if (!\in_array($alias, $joins, true)) {
                        $qb->leftJoin("{$parentAlias}.{$child}", $alias);
                        $joins[] = $alias;
                    }
                }

                if ('partial' === $mode) {
                    //search each word separate
                    $searchArray = explode(' ', $search);

                    $partialAnd = new Andx();
                    foreach ($searchArray as $q) {
                        $q = trim($q);
                        $partialAnd->add("$alias.$column LIKE '%$q%'");
                    }
                    $orx->add($partialAnd);
                } else {
                    $q = trim($search);
                    $orx->add("$alias.$column LIKE '$q'");
                }
            }

            $qb->andWhere($orx);
        }
    }
756178
public function search(string $id = '')
    {
        $model = $this->modelClass;

        /** @var \Search\Model\Table\SavedSearchesTable */
        $searchTable = TableRegistry::get($this->tableName);
        $table = $this->loadModel();
        $search = new Search($table, $this->Auth->user());

        if (!$searchTable->isSearchable($model) && !$this->Auth->user('is_admin')) {
            throw new BadRequestException('You cannot search in ' . implode(' - ', pluginSplit($model)) . '.');
        }

        // redirect on POST requests (PRG pattern)
        if ($this->request->is('post')) {
            $searchData = $search->prepareData($this->request);

            if ('' !== $id) {
                $search->update($searchData, $id);
            }

            if ('' === $id) {
                $id = $search->create($searchData);
            }

            list($plugin, $controller) = pluginSplit($model);

            return $this->redirect(['plugin' => $plugin, 'controller' => $controller, 'action' => __FUNCTION__, $id]);
        }

        $entity = $search->get($id);

        $searchData = $entity->get('content');

        // return json response and skip any further processing.
        if ($this->request->is('ajax') && $this->request->accepts('application/json')) {
            $this->viewBuilder()->setClassName('Json');
            $response = $this->getAjaxViewVars($searchData['latest'], $table, $search);
            $this->set($response);

            return;
        }

        $searchData = SearchValidator::validateData($table, $searchData['latest'], $this->Auth->user());

        // reset should only be applied to current search id (url parameter)
        // and NOT on newly pre-saved searches and that's we do the ajax
        // request check above, to prevent resetting the pre-saved search.
        $search->reset($entity);

        $this->set('searchableFields', Utility::instance()->getSearchableFields($table, $this->Auth->user()));

        $savedSearches = $searchTable->find('all')
            ->where([
                'SavedSearches.name IS NOT' => null,
                'SavedSearches.system' => false,
                'SavedSearches.user_id' => $this->Auth->user('id'),
                'SavedSearches.model' => $model
            ])
            ->toArray();

        $this->set('savedSearches', $savedSearches);
        $this->set('model', $model);
        $this->set('searchData', $searchData);
        $this->set('savedSearch', $entity);
        $this->set('preSaveId', $search->create($searchData));
        // INFO: this is valid when a saved search was modified and the form was re-submitted
        $this->set('searchOptions', SearchOptions::get());
        $this->set('associationLabels', Utility::instance()->getAssociationLabels($table));

        $this->render($this->searchElement);
    }
884619
public function searchAction()
    {
        $optionsProvider = $this->getOptionsProvider();
        $pane = $this->params()->fromRoute('pane');
        if (! $pane || ! $optionsProvider->hasIdentifier($pane)) {
            $pane = 'first';
        }

        $options = $optionsProvider->getOptions($pane, 'search');

        $search = $optionsProvider->getSearchProxy($pane);
        $form = $this->getSearchForm();
        $form->setAttribute(
            'action',
            $this->url()->fromRoute(
                'sc-admin/content-search',
                ['pane' => $pane]
            )
        );
        $form->bind($search);
        if ($this->getRequest()->isPost()) {
            $post = $this->params()->fromPost();
            if (array_key_exists('clean', $post)) {
                $search->clean();
            } else {
                $form->setData($post);
            }
            if ($form->isValid()) {
                $options->setSearchOptions(
                    $form->getData(ContentSearchForm::VALUES_AS_ARRAY)
                );
                $optionsProvider->save($options->getName());
            }
        }
        $list = $this->getContentListProvider()->getList($pane);

        return new ViewModel([
            'options' => $options,
            'list' => $list,
            'pane' => $pane,
            'form' => $form,
        ]);
    }
341048
public function findModel($id = false, $search = false)
    {
        $class = static::getModelClass($this->modelName) . ($search ? 'Search' : '');
        $model = new $class();
        if ($id && (!$model = $model->search(compact('id'))->one())) {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
        return $model;
    }
1233620
private void addFieldsToBuilder(String[] fieldsToSelect, Class clazz, MetamodelImpl metaModel,
            SearchRequestBuilder builder)
    {
        if (fieldsToSelect != null && fieldsToSelect.length > 1 && !(fieldsToSelect[1] == null))
        {
            logger.debug("Fields added in query are: ");
            for (int i = 1; i < fieldsToSelect.length; i++)
            {
                logger.debug(i + " : " + fieldsToSelect[i]);
                builder = builder.addField(((AbstractAttribute) metaModel.entity(clazz).getAttribute(fieldsToSelect[i]))
                        .getJPAColumnName());
            }
        }
    }
454705
protected function _addSearch(\Doctrine\ORM\QueryBuilder $queryBuilder)
    {
        if ($this->search == TRUE)
        {
            $request       = $this->request;
            $search_fields = array_values($this->fields);
            foreach ($search_fields as $i => $search_field)
            {
                $search_param = $request->get("sSearch_{$i}");
                if ($search_param !== false && $search_param != '')
                {
                    $field        = explode(' ', trim($search_field));
                    $search_field = $field[0];

                    $queryBuilder->andWhere(" $search_field like :ssearch{$i} ");
                    $queryBuilder->setParameter("ssearch{$i}", '%' . $request->get("sSearch_{$i}") . '%');
                }
            }
        }
    }
1373478
public function actionAdvancedSearch()
    {
        $dataProvider = null;
        $list = [];

        $model = new SearchForm;
        $model->setParams();

        if ($model->nextPage) {
            $dataProvider = $model->searchAdvanced();
        } else {
            $categories = Category::find()->orderBy(['name' => SORT_ASC]);
            $forums = Forum::find()->orderBy(['name' => SORT_ASC]);

            foreach ($categories->each() as $cat) {
                $catlist = [];
                foreach ($forums->each() as $for) {
                    if ($for->category_id == $cat->id) {
                        $catlist[$for->id] = '|-- ' . Html::encode($for->name);
                    }
                }
                $list[Html::encode($cat->name)] = $catlist;
            }

            if ($model->load(Yii::$app->request->post()) && $model->validate()) {
                if (empty($model->query) && empty($model->author)) {
                    $this->error(Yii::t('podium/flash', "You have to enter words or author's name first."));
                } else {
                    $stop = false;
                    if (!empty($model->query)) {
                        $words = explode(' ', preg_replace('/\s+/', ' ', $model->query));
                        $checkedWords = [];
                        foreach ($words as $word) {
                            if (mb_strlen($word, 'UTF-8') > 2) {
                                $checkedWords[] = $word;
                            }
                        }
                        $model->query = implode(' ', $checkedWords);
                        if (mb_strlen($model->query, 'UTF-8') < 3) {
                            $this->error(Yii::t('podium/flash', 'You have to enter word at least 3 characters long.'));
                            $stop = true;
                        }
                    }
                    if (!$stop) {
                        $dataProvider = $model->searchAdvanced();
                    }
                }
            }
        }

        return $this->render('search', [
            'model' => $model,
            'list' => $list,
            'dataProvider' => $dataProvider,
            'query' => $model->query,
            'author' => $model->author,
        ]);
    }
1111833
void changedSearchType() {

        SearchType type = (SearchType)m_searchType.getValue();

        m_property.setVisible(type.isPropertySearch());
        m_searchPattern.setVisible(
            (!type.equals(SearchType.resourcetype)) & (!type.equals(SearchType.renameContainer)));
        m_resourceSearch.setVisible(type.equals(SearchType.resourcetype) | type.equals(SearchType.renameContainer));
        if ((!type.equals(SearchType.resourcetype)) & (!type.equals(SearchType.renameContainer))) {
            m_ignoreSubSites.setValue(Boolean.FALSE);
            m_ignoreSubSites.setVisible(false);
        } else {
            m_ignoreSubSites.setVisible(true);
        }

        m_searchIndex.setVisible(type.isSolrSearch());
        m_solrQuery.setVisible(type.isSolrSearch());
        updateReplace();
        m_xPath.setVisible(type.isContentValuesOnly());
        m_locale.setVisible(type.isContentValuesOnly());

        m_resourceType.setVisible(
            !type.isPropertySearch()
                & !type.equals(SearchType.resourcetype)
                & !type.equals(SearchType.renameContainer));

        IndexedContainer types = (IndexedContainer)m_resourceType.getContainerDataSource();
        types.removeAllContainerFilters();
        types.addContainerFilter(
            type.isContentValuesOnly() ? CmsVaadinUtils.FILTER_XML_CONTENTS : CmsVaadinUtils.FILTER_NO_FOLDERS);
    }
1299427
public function replace($search, $replace): FileDeclaration
    {
        $this->docComment->replace($search, $replace);
        $this->elements->replace($search, $replace);

        return $this;
    }
757351
public function addSearch(BaseSearch $search, string $key = null): self
    {
        if ($key) {
            $this->_searches[$key] = $search;
        } else {
            $this->_searches[] = $search;
        }

        return $this;
    }