Seditio Source
Root |
./othercms/PHPFusion 9.10.20/includes/classes/PHPFusion/Search/Search_Engine.php
<?php
/*-------------------------------------------------------+
| PHPFusion Content Management System
| Copyright (C) PHP Fusion Inc
| https://phpfusion.com/
+--------------------------------------------------------+
| Filename: Search_Engine.php
| Author: Frederick MC Chan
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
namespace PHPFusion\Search;

class
Search_Engine extends SearchModel {

    public static
$locale = [];

   
/*
     * Template
     * Adds a third option to replace output template.
     * Just extend and declare your own by mutating the following
     * strings.
     *
     * In order to access the variables, extend your class to Search_Engine!
     */
   
protected static $search_instance = NULL;

    protected function
__construct() {
       
parent::__construct();
       
self::$locale = fusion_get_locale('', LOCALE.LOCALESET.'search.php');
    }

   
/**
     * Returns the search engine instance
     *
     * @return null|static
     */
   
public static function getInstance() {
        if (
self::$search_instance === NULL) {
           
self::$search_instance = new static();
           
self::$search_instance->init();
        }

        return
self::$search_instance;
    }

   
/**
     * Controller for search form
     */
   
protected static function displaySearchForm() {
       
$locale = self::$locale;
       
add_to_title($locale['global_202']);
       
$form_elements = self::$form_config['form_elements'];

       
/*
         * Search Areas
         */
       
$options_table = [];
       
$options_table['radio_buttons'] = [];
        if (!empty(
self::$form_config['radio_button'])) {
            foreach (
self::$form_config['radio_button'] as $value) {
               
$options_table['radio_buttons'][] = $value;
            }
        }
       
$options_table['radio_buttons'][] = form_checkbox('stype', $locale['407'], self::get_param('stype'), [
           
'type'          => 'radio',
           
'value'         => 'all',
           
'onclick'       => 'display(this.value)',
           
'reverse_label' => TRUE
       
]);

       
/*
         * Date limit
         */
       
$disabled_status = FALSE;
        if (isset(
$form_elements[self::get_param('stype')]['disabled'])) {
           
$disabled_status = !empty($form_elements[self::get_param('stype')]['disabled']);
            if (
self::get_param('stype') != 'all') {
               
$disabled_status = in_array("datelimit", $form_elements[self::get_param('stype')]['disabled']);
            }
        }

        if (
self::get_param('stype') == "all") {
           
$disabled_status = TRUE;
        }

       
$search_areas = [];
       
$search_areas['datelimit'] = form_select('datelimit', '', self::get_param('datelimit'), [
           
'inner_width' => '150px',
           
'options'     => [
               
'0'        => $locale['421'],
               
'86400'    => $locale['422'],
               
'604800'   => $locale['423'],
               
'1209600'  => $locale['424'],
               
'2419200'  => $locale['425'],
               
'7257600'  => $locale['426'],
               
'14515200' => $locale['427']
            ],
           
'deactivate'  => $disabled_status
       
]);
       
$search_areas['title_message'] = form_checkbox('fields', $locale['430'], self::get_param('fields'), [
           
'type'          => 'radio',
           
'value'         => '2',
           
'reverse_label' => TRUE,
           
'input_id'      => 'fields1',
           
'class'         => 'm-b-0',
           
'deactivate'    => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("fields1", $form_elements[self::get_param('stype')]['disabled']))
        ]);
       
$search_areas['message'] = form_checkbox('fields', $locale['431'], self::get_param('fields'), [
           
'type'          => 'radio',
           
'value'         => '1',
           
'reverse_label' => TRUE,
           
'input_id'      => 'fields2',
           
'class'         => 'm-b-0',
           
'deactivate'    => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("fields2", $form_elements[self::get_param('stype')]['disabled']))
        ]);
       
$search_areas['title'] = form_checkbox('fields', $locale['432'], self::get_param('fields'), [
           
'type'          => 'radio',
           
'value'         => '0',
           
'reverse_label' => TRUE,
           
'input_id'      => 'fields3',
           
'class'         => 'm-b-0',
           
'deactivate'    => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("fields3", $form_elements[self::get_param('stype')]['disabled']))
        ]);

       
/*
         * Sort
         */
       
$sort = [];
       
$sort['sort'] = form_select('sort', '', self::get_param('sort'), [
           
'inner_width' => '150px',
           
'options'     => [
               
'datestamp' => $locale['441'],
               
'subject'   => $locale['442'],
               
'author'    => $locale['443']
            ],
           
'deactivate'  => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("sort", $form_elements[self::get_param('stype')]['disabled']))
        ]);
       
$sort['desc'] = form_checkbox('order', $locale['450'], self::get_param('order'), [
           
'type'          => 'radio',
           
'value'         => '0',
           
'reverse_label' => TRUE,
           
'input_id'      => 'order1',
           
'class'         => 'm-b-0',
           
'deactivate'    => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("order1", $form_elements[self::get_param('stype')]['disabled']))
        ]);
       
$sort['asc'] = form_checkbox('order', $locale['451'], self::get_param('order'), [
           
'type'          => 'radio',
           
'value'         => '1',
           
'reverse_label' => TRUE,
           
'input_id'      => 'order2',
           
'class'         => 'm-b-0',
           
'deactivate'    => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("order2", $form_elements[self::get_param('stype')]['disabled']))
        ]);

       
/*
         * Char list
         */
       
$char_areas = form_select('chars', '', self::get_param('chars'), [
           
'inner_width' => '150px',
           
'options'     => [
               
'50'  => '50',
               
'100' => '100',
               
'150' => '150',
               
'200' => '200'
           
],
           
'deactivate'  => (self::get_param('stype') != "all" && isset($form_elements[self::get_param('stype')]) && in_array("chars", $form_elements[self::get_param('stype')]['disabled']))
        ]);

       
/*
         * Bind
         */
       
$info = [
           
'openform'       => openform('advanced_search_form', 'post', BASEDIR.'search.php'),
           
'closeform'      => closeform(),
           
'search_text'    => form_text('stext', str_replace('[SITENAME]', fusion_get_settings('sitename'), self::$locale['400']), urldecode(self::get_param('stext')), ['inline' => FALSE, 'placeholder' => $locale['401']]),
           
'search_button'  => form_button('search', $locale['402'], $locale['402'], ['class' => 'btn-primary']),
           
'search_method'  => form_checkbox('method', '', self::get_param('method'),
                [
                   
"options"       => [
                       
'OR'  => $locale['403'],
                       
'AND' => $locale['404']
                    ],
                   
'type'          => 'radio',
                   
'reverse_label' => TRUE,
                ]),
           
'search_sources' => $options_table,
           
'search_areas'   => $search_areas,
           
'sort_areas'     => $sort,
           
'char_areas'     => $char_areas,
           
'title'          => str_replace('[SITENAME]', fusion_get_settings('sitename'), self::$locale['400'])
        ];

        echo
$info['openform'];
        echo
render_search($info);
        echo
$info['closeform'];

       
/*
         * Javascript
         */
       
$search_js = "function display(val) {switch (val) {";
        foreach (
$form_elements as $type => $array1) {
           
$search_js .= "case '".$type."':";
            foreach (
$array1 as $what => $array2) {
                foreach (
$array2 as $value) {
                    if (
$what == "enabled") {
                       
$search_js .= "document.getElementById('".$value."').disabled = false;";
                    } else {
                        if (
$what == "disabled") {
                           
$search_js .= "document.getElementById('".$value."').disabled = true;";
                        } else {
                            if (
$what == "display") {
                               
$search_js .= "document.getElementById('".$value."').style.display = 'block';";
                            } else {
                                if (
$what == "nodisplay") {
                                   
$search_js .= "document.getElementById('".$value."').style.display = 'none';";
                                }
                            }
                        }
                    }
                }
            }
           
$search_js .= "break;\n";
        }
       
$search_js .= "case 'all':\n";
       
$search_js .= "document.getElementById('datelimit').disabled = false;";
       
$search_js .= "document.getElementById('fields1').disabled = false;";
       
$search_js .= "document.getElementById('fields2').disabled = false;";
       
$search_js .= "document.getElementById('fields3').disabled = false;";
       
$search_js .= "document.getElementById('sort').disabled = false;";
       
$search_js .= "document.getElementById('order1').disabled = false;";
       
$search_js .= "document.getElementById('order2').disabled = false;";
       
$search_js .= "document.getElementById('chars').disabled = false;";
       
$search_js .= "break;}}";
       
add_to_footer('<script>'.jsminify($search_js).'</script>');
    }

   
/**
     * Returns params
     *
     * @param string $key
     *
     * @return array|string
     */
   
public static function get_param($key = NULL) {
       
$info = [];
        try {
           
$info = [
               
'stype'        => stripinput(self::$search_type),
               
'stext'        => stripinput(self::$search_text),
               
'method'       => stripinput(self::$search_method),
               
'datelimit'    => self::$search_date_limit,
               
'fields'       => self::$search_fields,
               
'sort'         => self::$search_sort,
               
'chars'        => stripinput(self::$search_chars),
               
'order'        => self::$search_order,
               
'forum_id'     => self::$forum_id,
               
'memory_limit' => self::$memory_limit,
               
'composevars'  => self::$composevars,
               
'rowstart'     => self::$rowstart,
               
'search_param' => self::$search_param,
            ];
        } catch (\
Exception $e) {
           
redirect(BASEDIR.fusion_get_settings('opening_page'));
        }


        return
$key === NULL ? $info : (isset($info[$key]) ? $info[$key] : NULL);
    }

   
/**
     * Controller for display the search results
     */
   
protected static function displayResults() {
       
$locale = self::$locale;
       
self::$composevars = "method=".self::get_param('method')."&datelimit=".self::get_param('datelimit')."&fields=".self::get_param('fields')."&sort=".self::get_param('sort')."&order=".self::get_param('order')."&chars=".self::get_param('chars')."&forum_id=".self::get_param('forum_id')."&";
       
add_to_title($locale['global_201'].$locale['408']);

       
$search_text = explode(' ', urldecode(self::$search_text));
       
$qualified_search_text = [];
       
$disqualified_search_text = [];

       
self::$fields_count = self::get_param('fields') + 1;
        for (
$i = 0, $k = 0; $i < count($search_text); $i++) {
            if (
strlen($search_text[$i]) >= 3) {
               
$qualified_search_text[] = htmlentities($search_text[$i]);
                for (
$j = 0; $j < self::$fields_count; $j++) {
                   
// It is splitting to 2 parts.
                   
self::$search_param[':sword'.$k.$j] = '%'.$search_text[$i].'%';
                }
               
$k++;
            } else {
               
$disqualified_search_text[] = $search_text[$i];
            }
        }
        unset(
$search_text);
       
self::$swords = $qualified_search_text;

       
self::$c_swords = count($qualified_search_text);
       
self::$i_swords = count($disqualified_search_text);

       
self::$swords_keys_for_query = array_keys(self::$search_param);
       
self::$swords_values_for_query = array_values(self::$search_param);

       
// Highlight using Jquery the words. This, can actually parse as settings.
       
$highlighted_text = "";
       
$i = 1;
        foreach (
$qualified_search_text as $value) {
           
$highlighted_text .= "'".$value."'";
           
$highlighted_text .= ($i < self::$c_swords ? "," : "");
           
$i++;
        }

       
add_to_footer("<script type='text/javascript' src='".INCLUDES."jquery/jquery.highlight.js'></script>");
       
add_to_jquery("$('.search_result .results').highlight([".$highlighted_text."],{wordsOnly:true}); $('.highlight').css({backgroundColor:'#FFFF88'});");

       
/*
         * Run the drivers via include. but this method need to change to simplify the kiss concept.
         */
       
if (self::get_param('stype') == "all") {
           
$search_deffiles = [];
           
$search_includefiles = makefilelist(INCLUDES.'search/', '.|..|index.php|location.json.php|users.json.php|.DS_Store', TRUE);
           
$search_infusionfiles = makefilelist(INFUSIONS, '.|..|index.php', TRUE, 'folders');
            if (!empty(
$search_infusionfiles)) {
                foreach (
$search_infusionfiles as $files_to_check) {
                    if (
is_dir(INFUSIONS.$files_to_check.'/search/')) {
                       
$search_checkfiles = makefilelist(INFUSIONS.$files_to_check.'/search/', ".|..|index.php", TRUE);
                       
$search_deffiles = array_merge($search_deffiles, $search_checkfiles);
                    }
                }
            }
           
$search_files = array_merge($search_includefiles, $search_deffiles);

            foreach (
$search_files as $file_to_check) {
                if (
preg_match("/include.php/i", $file_to_check)) {
                    if (
file_exists(INCLUDES."search/".$file_to_check)) {
                       
self::loadDriver(INCLUDES."search/".$file_to_check);
                    }

                    foreach (
$search_infusionfiles as $inf_files_to_check) {
                        if (
file_exists(INFUSIONS.$inf_files_to_check.'/search/'.$file_to_check)) {
                           
self::loadDriver(INFUSIONS.$inf_files_to_check.'/search/'.$file_to_check);
                        }
                    }
                }
            }
        } else {
            if (
file_exists(INCLUDES."search/search_".self::get_param('stype')."_include.php")) {
               
self::loadDriver(INCLUDES."search/search_".self::get_param('stype')."_include.php");
            }

           
$search_infusionfiles = makefilelist(INFUSIONS, '.|..|index.php', TRUE, 'folders');
            foreach (
$search_infusionfiles as $inf_files_to_check) {
                if (
file_exists(INFUSIONS.$inf_files_to_check.'/search/search_'.self::get_param('stype').'_include.php')) {
                   
self::loadDriver(INFUSIONS.$inf_files_to_check.'/search/search_'.self::get_param('stype').'_include.php');
                }
            }
        }

       
$info = [];

       
// Show how many disqualified search texts
       
$c_iwords = count($disqualified_search_text);
        if (
$c_iwords) {
           
$txt = "";
            for (
$i = 0; $i < $c_iwords; $i++) {
               
$txt .= $disqualified_search_text[$i].($i < $c_iwords - 1 ? ", " : "");
            }

           
$info['disqualified_stexts'] = sprintf($locale['502'], $txt);
        }

       
/*
         * HTML output
         */
       
$info['search_count'] = self::$items_count;
        if (
self::get_param('stype') == "all") {
           
ob_start();
           
parent::search_navigation(0);
           
$info['navigation'] = ob_get_contents();
           
ob_end_clean();
           
$info['result_text'] = ((self::$site_search_count > 100 || parent::search_globalarray("")) ? "<br/>".sprintf($locale['530'], self::$site_search_count) : "<br/>".self::$site_search_count." ".$locale['510']);
        } else {
           
$info['result_text'] = ((self::$site_search_count > 100 || parent::search_globalarray("")) ? "<br/><strong>".sprintf($locale['530'], self::$site_search_count)."</strong>" : (empty(self::$site_search_count) ? $locale['500'] : ''));
        }

       
$info['results'] = implode('', self::$search_result_array);

       
$info['navigation_result'] = '';
        if (
self::get_param('stype') != "all") {
           
$info['navigation_result'] = self::$navigation_result;
        }

        echo
render_search_count($info);
    }

   
/**
     * Load the search driver file
     * - Prevents string mutation
     *
     * @param string $path
     */
   
protected static function loadDriver($path) {
        include_once(
$path);
    }

   
/**
     * Controller for omitting search
     */
   
protected static function displayNoResults() {
       
$locale = self::$locale;
       
add_to_title($locale['global_201'].$locale['408']);
        echo
render_search_no_result([
           
'title'   => $locale['408'],
           
'content' => $locale['501'],
        ]);
    }

   
/**
     * Prevents class cloning
     */
   
private function __clone() {
    }

    public static function
displaySearch() {
        echo
'<div class="search-page">';
       
self::displaySearchForm();
        if (
strlen(self::get_param('stext')) >= 3) {
           
self::displayResults();
        } else if (
check_post('stext')) {
           
self::displayNoResults();
        }
        echo
'</div>';
    }
}