private function _calculateRelevancy(){ // Lowercase it. $query = strtolower($this->query); // Convert this string to latin. $query = \Core\str_to_latin($query); // Skip punctuation. $query = preg_replace('/[^a-z0-9 ]/', '', $query); // Split out words. $parts = explode(' ', $query); $ignore = Helper::GetSkipWords(); foreach($parts as $k => $word){ // Skip blank words. if(!$word){ unset($parts[$k]); continue; } // Unset any to-be-skipped word. if(in_array($word, $ignore)){ unset($parts[$k]); continue; } } // All query words in the result mean 100% relevancy. $size = sizeof($parts); if(!$size){ $this->relevancy = 0; return; } $wordweight = 100 / $size; // And each word has 3 parts to it. $wordweight /= 3; $rel = 0.0; $str = explode(' ', $this->_model->get('search_index_str')); $pri = explode(' ', $this->_model->get('search_index_pri')); $sec = explode(' ', $this->_model->get('search_index_sec')); foreach($parts as $word){ $it = new DoubleMetaPhone($word); if(in_array($word, $str)){ // Exact matches here get an automatic boost! $rel += ($wordweight * 3); } else{ foreach($str as $w){ if(strpos($w, $word) !== false){ // If a partial match is located, add a fraction of the word weight, (since it wasn't a complete match). $rel += $wordweight * (strlen($word) / strlen($w)); break; } } } if(in_array($it->primary, $pri)) $rel += $wordweight; if(in_array($it->secondary, $sec)) $rel += $wordweight; } $this->relevancy = min($rel, 100); }
/** * Perform a model search on the records of this Model. * * @param string $query The base query to search * @param array $where Any additional where parameters to add onto the factory * * @return array An array of ModelResult objects. */ public static function Search($query, $where = []){ $ret = []; // If this object does not support searching, simply return an empty array. $ref = new ReflectionClass(get_called_class()); if(!$ref->getProperty('HasSearch')->getValue()){ return $ret; } $fac = new ModelFactory(get_called_class()); if(sizeof($where)){ $fac->where($where); } if($ref->getProperty('HasDeleted')->getValue()){ $fac->where('deleted = 0'); } $fac->where(\Core\Search\Helper::GetWhereClause($query)); foreach($fac->get() as $m){ /** @var Model $m */ $sr = new \Core\Search\ModelResult($query, $m); // This may happen since the where clause can be a little open-ended. if($sr->relevancy < 1) continue; $sr->title = $m->getLabel(); $sr->link = $m->get('baseurl'); $ret[] = $sr; } // Sort the results before returning them. // Because otherwise, what's the point of a search algorithm?!? usort($ret, function($a, $b) { /** @var $a Core\Search\ModelResult */ /** @var $b Core\Search\ModelResult */ return $a->relevancy < $b->relevancy; }); return $ret; }
/** * View controller for a blog article listing page. * This will only display articles under this same blog. * * @param BlogModel $blog */ private function _viewBlog(BlogModel $blog) { $view = $this->getView(); $page = $blog->getLink('Page'); $request = $this->getPageRequest(); $manager = \Core\user()->checkAccess('p:/blog/manage_all'); $editor = \Core\user()->checkAccess($blog->get('manage_articles_permission ')) || $manager; $viewer = \Core\user()->checkAccess($blog->get('access')) || $editor; // Get the latest published article's update date. This will be used for the blog updated timestamp. // (This doesn't have a whole lot of benefit above the ModelFactory, simply illustrating a different way to query data). $latest = \Core\Datamodel\Dataset::Init()->select('*')->table('page')->where('parenturl = ' . $blog->get('baseurl'))->where('published_status = published')->order('published DESC')->limit(1)->current(); $filters = new FilterForm(); $filters->haspagination = true; // Allow different type of requests to come in here. switch ($request->ctype) { case 'application/atom+xml': $view->templatename = 'pages/blog/view-blog.atom.tpl'; $view->contenttype = $request->ctype; $view->mastertemplate = false; $filters->setLimit(200); break; case 'application/rss+xml': $view->templatename = 'pages/blog/view-blog.rss.tpl'; $view->contenttype = $request->ctype; $view->mastertemplate = false; $filters->setLimit(200); break; default: $view->templatename = 'pages/blog/view-blog.tpl'; $filters->setLimit(20); break; } $filters->load($this->getPageRequest()); $factory = new ModelFactory('PageModel'); if ($request->getParameter('q')) { $query = $request->getParameter('q'); $factory->where(\Core\Search\Helper::GetWhereClause($request->getParameter('q'))); } else { $query = null; } $factory->where('parenturl = ' . $blog->get('baseurl')); $factory->order('published DESC'); if (!$editor) { // Limit these to published articles. $factory->where('published_status = published'); // And where the published date is >= now. $factory->where('published <= ' . CoreDateTime::Now('U', Time::TIMEZONE_GMT)); } $filters->applyToFactory($factory); $articles = $factory->get(); $view->mode = View::MODE_PAGEORAJAX; $view->assign('blog', $blog); $view->assign('articles', $articles); $view->assign('page', $page); $view->assign('filters', $filters); $view->assign('canonical_url', \Core\resolve_link($blog->get('baseurl'))); $view->assign('last_updated', $latest ? $latest['updated'] : 0); $view->assign('servername', SERVERNAME_NOSSL); $view->assign('editor', $editor); $view->assign('add_article_link', '/content/create?page_template=blog-article.tpl&parenturl=' . $blog->get('baseurl')); // Add the extra view types for this page $view->addHead('<link rel="alternate" type="application/atom+xml" title="' . $page->get('title') . ' Atom Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.atom"/>'); $view->addHead('<link rel="alternate" type="application/rss+xml" title="' . $page->get('title') . ' RSS Feed" href="' . \Core\resolve_link($blog->get('baseurl')) . '.rss"/>'); if ($editor) { if ($blog->get('type') == 'remote') { $view->addControl('Import Feed', '/blog/import/' . $blog->get('id'), 'exchange'); } else { $view->addControl('Add Article', '/content/create?page_template=blog-article.tpl&parenturl=' . $blog->get('baseurl'), 'add'); } } if ($manager) { $view->addControl('Edit Blog', '/blog/update/' . $blog->get('id'), 'edit'); $view->addControl('All Articles', '/admin/pages/?filter[parenturl]=' . $blog->get('baseurl'), 'tasks'); } $view->addControl('RSS Feed', \Core\resolve_link($blog->get('baseurl')) . '.rss', 'rss'); //$view->addControl('Atom Feed', \Core\resolve_link($blog->get('baseurl')) . '.atom', 'rss'); }