first commit
This commit is contained in:
12
administrator/components/com_finder/access.xml
Normal file
12
administrator/components/com_finder/access.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<access component="com_finder">
|
||||
<section name="component">
|
||||
<action name="core.admin" title="JACTION_ADMIN" />
|
||||
<action name="core.options" title="JACTION_OPTIONS" />
|
||||
<action name="core.manage" title="JACTION_MANAGE" />
|
||||
<action name="core.create" title="JACTION_CREATE" />
|
||||
<action name="core.delete" title="JACTION_DELETE" />
|
||||
<action name="core.edit" title="JACTION_EDIT" />
|
||||
<action name="core.edit.state" title="JACTION_EDITSTATE" />
|
||||
</section>
|
||||
</access>
|
||||
414
administrator/components/com_finder/config.xml
Normal file
414
administrator/components/com_finder/config.xml
Normal file
@ -0,0 +1,414 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config>
|
||||
<help key="Smart_Search:_Options"/>
|
||||
<inlinehelp button="show"/>
|
||||
<fieldset
|
||||
name="search"
|
||||
label="COM_FINDER_FIELDSET_SEARCH_OPTIONS_LABEL"
|
||||
>
|
||||
<field
|
||||
name="word_match"
|
||||
type="list"
|
||||
label="COM_FINDER_CONFIG_WORD_MATCH_LABEL"
|
||||
description="COM_FINDER_CONFIG_WORD_MATCH_DESC"
|
||||
default="exact"
|
||||
>
|
||||
<option value="exact">COM_FINDER_CONFIG_WORD_MATCH_OPTION_EXACT</option>
|
||||
<option value="begin">COM_FINDER_CONFIG_WORD_MATCH_OPTION_BEGIN</option>
|
||||
<option value="fuzzy">COM_FINDER_CONFIG_WORD_MATCH_OPTION_FUZZY</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_taxonomy"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_TAXONOMY_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_description"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_DESCRIPTION_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="description_length"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_DESCRIPTION_LENGTH_LABEL"
|
||||
default="255"
|
||||
filter="integer"
|
||||
showon="show_description:1"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="show_image"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_IMAGE_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="image_class"
|
||||
type="text"
|
||||
label="COM_FINDER_CONFIG_IMAGE_CLASS_LABEL"
|
||||
validate="CssIdentifier"
|
||||
showon="show_image:1"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="link_image"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_LINKED_IMAGE_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
showon="show_image:1"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_date"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_DATE_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_url"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_URL_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="gather_search_statistics"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="allow_empty_query"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_ALLOW_EMPTY_QUERY_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_autosuggest"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_AUTOSUGGEST_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_suggested_query"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_explained_query"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_advanced"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_ADVANCED_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_advanced_tips"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_ADVANCED_TIPS_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
showon="show_advanced:1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="expand_advanced"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_EXPAND_ADVANCED_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
showon="show_advanced:1"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="show_date_filters"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_SHOW_DATE_FILTERS_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
showon="show_advanced:1"
|
||||
>
|
||||
<option value="0">JHIDE</option>
|
||||
<option value="1">JSHOW</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="sort_order"
|
||||
type="list"
|
||||
label="COM_FINDER_CONFIG_SORT_ORDER_LABEL"
|
||||
default="relevance"
|
||||
validate="options"
|
||||
>
|
||||
<option value="relevance">COM_FINDER_CONFIG_SORT_OPTION_RELEVANCE</option>
|
||||
<option value="title">COM_FINDER_CONFIG_SORT_OPTION_TITLE</option>
|
||||
<option value="date">COM_FINDER_CONFIG_SORT_OPTION_START_DATE</option>
|
||||
<option value="price">COM_FINDER_CONFIG_SORT_OPTION_LIST_PRICE</option>
|
||||
<option value="sale_price">COM_FINDER_CONFIG_SORT_OPTION_SALES_PRICE</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="sort_direction"
|
||||
type="list"
|
||||
label="COM_FINDER_CONFIG_SORT_DIRECTION_LABEL"
|
||||
default="desc"
|
||||
validate="options"
|
||||
>
|
||||
<option value="desc">COM_FINDER_CONFIG_SORT_OPTION_DESCENDING</option>
|
||||
<option value="asc">COM_FINDER_CONFIG_SORT_OPTION_ASCENDING</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="highlight_terms"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_LABEL"
|
||||
description="COM_FINDER_CONFIG_HIGHLIGHT_CONTENT_SEARCH_TERMS_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="opensearch"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_OPENSEARCH_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="opensearch_name"
|
||||
type="text"
|
||||
label="COM_FINDER_CONFIG_FIELD_OPENSEARCH_NAME_LABEL"
|
||||
default=""
|
||||
showon="opensearch:1"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="opensearch_description"
|
||||
type="textarea"
|
||||
label="COM_FINDER_CONFIG_FIELD_OPENSEARCH_DESCRIPTION_LABEL"
|
||||
default=""
|
||||
cols="30"
|
||||
rows="2"
|
||||
showon="opensearch:1"
|
||||
/>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
name="index"
|
||||
label="COM_FINDER_FIELDSET_INDEX_OPTIONS_LABEL"
|
||||
description="COM_FINDER_FIELDSET_INDEX_OPTIONS_DESCRIPTION"
|
||||
>
|
||||
|
||||
<field
|
||||
name="tuplecount"
|
||||
type="list"
|
||||
label="COM_FINDER_CONFIG_TUPLECOUNT_LABEL"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">COM_FINDER_CONFIG_TUPLECOUNT_PHRASE_DISABLED</option>
|
||||
<option value="3">COM_FINDER_CONFIG_TUPLECOUNT_PHRASE_ENABLED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="batch_size"
|
||||
type="list"
|
||||
label="COM_FINDER_CONFIG_BATCH_SIZE_LABEL"
|
||||
default="50"
|
||||
validate="options"
|
||||
>
|
||||
<option value="5">J5</option>
|
||||
<option value="10">J10</option>
|
||||
<option value="25">J25</option>
|
||||
<option value="50">J50</option>
|
||||
<option value="75">J75</option>
|
||||
<option value="100">J100</option>
|
||||
<option value="150">J150</option>
|
||||
<option value="200">J200</option>
|
||||
<option value="250">J250</option>
|
||||
<option value="300">J300</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="title_multiplier"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_TITLE_MULTIPLIER_LABEL"
|
||||
default="1.7"
|
||||
min="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="text_multiplier"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_TEXT_MULTIPLIER_LABEL"
|
||||
default="0.7"
|
||||
min="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="meta_multiplier"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_META_MULTIPLIER_LABEL"
|
||||
default="1.2"
|
||||
min="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="path_multiplier"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_PATH_MULTIPLIER_LABEL"
|
||||
default="2.0"
|
||||
min="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="misc_multiplier"
|
||||
type="number"
|
||||
label="COM_FINDER_CONFIG_MISC_MULTIPLIER_LABEL"
|
||||
default="0.3"
|
||||
min="0"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="enable_logging"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_ENABLE_LOGGING_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="language_default"
|
||||
type="language"
|
||||
label="COM_FINDER_CONFIG_LANGUAGE_DEFAULT_LABEL"
|
||||
description="COM_FINDER_CONFIG_LANGUAGE_DEFAULT_DESC"
|
||||
>
|
||||
<option value="-1">COM_FINDER_CONFIG_LANGUAGE_DEFAULT_DEFAULT_LANGUAGE</option>
|
||||
<option value="">COM_FINDER_CONFIG_LANGUAGE_DEFAULT_NONE</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="filter_commonwords"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_FILTER_COMMONWORDS_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="filter_numerics"
|
||||
type="radio"
|
||||
label="COM_FINDER_CONFIG_FILTER_NUMERICS_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
name="permissions"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
>
|
||||
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
filter="rules"
|
||||
validate="rules"
|
||||
component="com_finder"
|
||||
section="component"
|
||||
/>
|
||||
|
||||
</fieldset>
|
||||
</config>
|
||||
56
administrator/components/com_finder/finder.xml
Normal file
56
administrator/components/com_finder/finder.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_finder</name>
|
||||
<author>Joomla! Project</author>
|
||||
<copyright>(C) 2011 Open Source Matters, Inc.</copyright>
|
||||
<creationDate>2011-08</creationDate>
|
||||
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
|
||||
<authorEmail>admin@joomla.org</authorEmail>
|
||||
<authorUrl>www.joomla.org</authorUrl>
|
||||
<version>4.0.0</version>
|
||||
<description>COM_FINDER_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Component\Finder</namespace>
|
||||
<menu link="option=com_finder">COM_FINDER</menu>
|
||||
<install>
|
||||
<sql>
|
||||
<file charset="utf8" driver="mysql">sql/install.mysql.sql</file>
|
||||
<file charset="utf8" driver="postgresql">sql/install.postgresql.sql</file>
|
||||
</sql>
|
||||
</install>
|
||||
<uninstall>
|
||||
<sql>
|
||||
<file charset="utf8" driver="mysql">sql/uninstall.mysql.sql</file>
|
||||
<file charset="utf8" driver="postgresql">sql/uninstall.postgresql.sql</file>
|
||||
</sql>
|
||||
</uninstall>
|
||||
<files folder="site">
|
||||
<folder>helpers</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<media destination="com_finder" folder="media">
|
||||
<folder>css</folder>
|
||||
<folder>js</folder>
|
||||
</media>
|
||||
<languages folder="site">
|
||||
<language tag="en-GB">language/en-GB/com_finder.ini</language>
|
||||
</languages>
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<filename>access.xml</filename>
|
||||
<filename>config.xml</filename>
|
||||
<filename>finder.xml</filename>
|
||||
<folder>forms</folder>
|
||||
<folder>helpers</folder>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>sql</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<languages folder="admin">
|
||||
<language tag="en-GB">language/en-GB/com_finder.ini</language>
|
||||
<language tag="en-GB">language/en-GB/com_finder.sys.ini</language>
|
||||
</languages>
|
||||
<menu img="class:search-plus" link="option=com_finder">COM_FINDER</menu>
|
||||
</administration>
|
||||
</extension>
|
||||
154
administrator/components/com_finder/forms/filter.xml
Normal file
154
administrator/components/com_finder/forms/filter.xml
Normal file
@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset>
|
||||
<field
|
||||
name="filter_id"
|
||||
type="text"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
class="readonly"
|
||||
default="0"
|
||||
readonly="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="JGLOBAL_TITLE"
|
||||
required="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="alias"
|
||||
type="text"
|
||||
label="JFIELD_ALIAS_LABEL"
|
||||
description="JFIELD_ALIAS_DESC"
|
||||
hint="JFIELD_ALIAS_PLACEHOLDER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="created"
|
||||
type="calendar"
|
||||
label="JGLOBAL_FIELD_CREATED_LABEL"
|
||||
translateformat="true"
|
||||
showtime="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="modified"
|
||||
type="calendar"
|
||||
label="JGLOBAL_FIELD_MODIFIED_LABEL"
|
||||
class="readonly"
|
||||
translateformat="true"
|
||||
showtime="true"
|
||||
readonly="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="created_by"
|
||||
type="user"
|
||||
label="COM_FINDER_FIELD_CREATED_BY_LABEL"
|
||||
validate="UserId"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="created_by_alias"
|
||||
type="text"
|
||||
label="COM_FINDER_FIELD_CREATED_BY_ALIAS_LABEL"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="modified_by"
|
||||
type="user"
|
||||
label="JGLOBAL_FIELD_MODIFIED_BY_LABEL"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
filter="unset"
|
||||
validate="UserId"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="checked_out"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="checked_out_time"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="state"
|
||||
type="list"
|
||||
label="JSTATUS"
|
||||
class="form-select-color-state"
|
||||
filter="intval"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">JPUBLISHED</option>
|
||||
<option value="0">JUNPUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="map_count"
|
||||
type="text"
|
||||
label="COM_FINDER_FILTER_MAP_COUNT"
|
||||
class="readonly"
|
||||
default="0"
|
||||
readonly="true"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fields name="params">
|
||||
<fieldset name="jbasic" label="COM_FINDER_FILTER_FIELDSET_PARAMS">
|
||||
<field
|
||||
name="w1"
|
||||
type="list"
|
||||
label="COM_FINDER_FILTER_WHEN_START_DATE_LABEL"
|
||||
default=""
|
||||
filter="string"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JNONE</option>
|
||||
<option value="-1">COM_FINDER_FILTER_WHEN_BEFORE</option>
|
||||
<option value="0">COM_FINDER_FILTER_WHEN_EXACTLY</option>
|
||||
<option value="1">COM_FINDER_FILTER_WHEN_AFTER</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="d1"
|
||||
type="calendar"
|
||||
label="COM_FINDER_FILTER_START_DATE_LABEL"
|
||||
translateformat="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="w2"
|
||||
type="list"
|
||||
label="COM_FINDER_FILTER_WHEN_END_DATE_LABEL"
|
||||
default=""
|
||||
filter="string"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JNONE</option>
|
||||
<option value="-1">COM_FINDER_FILTER_WHEN_BEFORE</option>
|
||||
<option value="0">COM_FINDER_FILTER_WHEN_EXACTLY</option>
|
||||
<option value="1">COM_FINDER_FILTER_WHEN_AFTER</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="d2"
|
||||
type="calendar"
|
||||
label="COM_FINDER_FILTER_END_DATE_LABEL"
|
||||
translateformat="true"
|
||||
filter="user_utc"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
</fields>
|
||||
</form>
|
||||
56
administrator/components/com_finder/forms/filter_filters.xml
Normal file
56
administrator/components/com_finder/forms/filter_filters.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_FINDER_SEARCH_FILTER_SEARCH_LABEL"
|
||||
description="COM_FINDER_SEARCH_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="state"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
optionsFilter="0,1"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="a.title ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="a.state ASC">JSTATUS_ASC</option>
|
||||
<option value="a.state DESC">JSTATUS_DESC</option>
|
||||
<option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
|
||||
<option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
|
||||
<option value="a.created_by_alias ASC">COM_FINDER_HEADING_CREATED_BY_ASC</option>
|
||||
<option value="a.created_by_alias DESC">COM_FINDER_HEADING_CREATED_BY_DESC</option>
|
||||
<option value="a.created ASC">COM_FINDER_HEADING_CREATED_ON_ASC</option>
|
||||
<option value="a.created DESC">COM_FINDER_HEADING_CREATED_ON_DESC</option>
|
||||
<option value="a.map_count ASC">COM_FINDER_HEADING_MAP_COUNT_ASC</option>
|
||||
<option value="a.map_count DESC">COM_FINDER_HEADING_MAP_COUNT_DESC</option>
|
||||
<option value="a.filter_id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="a.filter_id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
84
administrator/components/com_finder/forms/filter_index.xml
Normal file
84
administrator/components/com_finder/forms/filter_index.xml
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Finder\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_FINDER_INDEX_SEARCH_LABEL"
|
||||
description="COM_FINDER_INDEX_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="state"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
optionsFilter="0,1"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="type"
|
||||
type="contenttypes"
|
||||
label="COM_FINDER_MAPS_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_FINDER_MAPS_SELECT_TYPE</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="content_map"
|
||||
type="contentmap"
|
||||
label="COM_FINDER_MAPS_HEADING_CONTENT_MAP"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_FINDER_FILTER_SELECT_CONTENT_MAP</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="language"
|
||||
type="contentlanguage"
|
||||
label="JGRID_HEADING_LANGUAGE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_LANGUAGE</option>
|
||||
<option value="*">JALL</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="l.title ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="l.published ASC">JSTATUS_ASC</option>
|
||||
<option value="l.published DESC">JSTATUS_DESC</option>
|
||||
<option value="l.title ASC">JGLOBAL_TITLE_ASC</option>
|
||||
<option value="l.title DESC">JGLOBAL_TITLE_DESC</option>
|
||||
<option value="t.title ASC">COM_FINDER_INDEX_HEADING_INDEX_TYPE_ASC</option>
|
||||
<option value="t.title DESC">COM_FINDER_INDEX_HEADING_INDEX_TYPE_DESC</option>
|
||||
<option value="l.indexdate ASC">COM_FINDER_INDEX_HEADING_INDEX_DATE_ASC</option>
|
||||
<option value="l.indexdate DESC">COM_FINDER_INDEX_HEADING_INDEX_DATE_DESC</option>
|
||||
<option value="l.language ASC" requires="multilanguage">JGRID_HEADING_LANGUAGE_ASC</option>
|
||||
<option value="l.language DESC" requires="multilanguage">JGRID_HEADING_LANGUAGE_DESC</option>
|
||||
<option value="l.url ASC">COM_FINDER_INDEX_HEADING_LINK_URL_ASC</option>
|
||||
<option value="l.url DESC">COM_FINDER_INDEX_HEADING_LINK_URL_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
71
administrator/components/com_finder/forms/filter_maps.xml
Normal file
71
administrator/components/com_finder/forms/filter_maps.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Finder\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_FINDER_SEARCH_SEARCH_QUERY_LABEL"
|
||||
description="COM_FINDER_SEARCH_SEARCH_QUERY_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="state"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
optionsFilter="0,1"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="branch"
|
||||
type="branches"
|
||||
label="COM_FINDER_MAPS_HEADING_BRANCH"
|
||||
default="0"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="level"
|
||||
type="integer"
|
||||
label="JGLOBAL_MAXLEVEL_LABEL"
|
||||
first="1"
|
||||
last="2"
|
||||
step="1"
|
||||
languages="*"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_MAX_LEVELS</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="branch_title ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="a.state ASC">JSTATUS_ASC</option>
|
||||
<option value="a.state DESC">JSTATUS_DESC</option>
|
||||
<option value="branch_title ASC, a.lft ASC">JGLOBAL_TITLE_ASC</option>
|
||||
<option value="branch_title DESC, a.lft DESC">JGLOBAL_TITLE_DESC</option>
|
||||
<option value="a.language ASC" requires="multilanguage">JGRID_HEADING_LANGUAGE_ASC</option>
|
||||
<option value="a.language DESC" requires="multilanguage">JGRID_HEADING_LANGUAGE_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_FINDER_SEARCH_IN_PHRASE_LABEL"
|
||||
description="COM_FINDER_SEARCH_IN_PHRASE_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
</fields>
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="a.hits ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="a.searchterm ASC">COM_FINDER_HEADING_SEARCH_TERM_ASC</option>
|
||||
<option value="a.searchterm DESC">COM_FINDER_HEADING_SEARCH_TERM_DESC</option>
|
||||
<option value="a.hits ASC">JGLOBAL_HITS_ASC</option>
|
||||
<option value="a.hits DESC">JGLOBAL_HITS_DESC</option>
|
||||
</field>
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
19
administrator/components/com_finder/forms/indexer.xml
Normal file
19
administrator/components/com_finder/forms/indexer.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset name="form">
|
||||
<field
|
||||
name="plugin"
|
||||
type="plugins"
|
||||
label="COM_FINDER_FIELD_FINDER_PLUGIN_LABEL"
|
||||
folder="finder"
|
||||
required="true"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="id"
|
||||
type="text"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
required="true"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Adapter class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Adapter instead
|
||||
*/
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Helper class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Helper instead
|
||||
*/
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Parser class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* 5.0 Use \Joomla\Component\Finder\Administrator\Indexer\Parser instead
|
||||
*/
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Query class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Query instead
|
||||
*/
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Result class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Result instead
|
||||
*/
|
||||
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Taxonomy class.
|
||||
*
|
||||
* @since 2.5
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Taxonomy instead
|
||||
*/
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
/**
|
||||
* Finder Indexer Token class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Indexer\Token instead
|
||||
*/
|
||||
29
administrator/components/com_finder/helpers/language.php
Normal file
29
administrator/components/com_finder/helpers/language.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
*/
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Finder language helper class.
|
||||
*
|
||||
* @since 2.5
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Finder\Administrator\Helper\LanguageHelper instead
|
||||
*/
|
||||
class FinderHelperLanguage extends LanguageHelper
|
||||
{
|
||||
}
|
||||
58
administrator/components/com_finder/services/provider.php
Normal file
58
administrator/components/com_finder/services/provider.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Component\Router\RouterFactoryInterface;
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\RouterFactory;
|
||||
use Joomla\CMS\HTML\Registry;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Component\Finder\Administrator\Extension\FinderComponent;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* The finder service provider.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Finder'));
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Finder'));
|
||||
$container->registerServiceProvider(new RouterFactory('\\Joomla\\Component\\Finder'));
|
||||
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
function (Container $container) {
|
||||
$component = new FinderComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
$component->setRouterFactory($container->get(RouterFactoryInterface::class));
|
||||
$component->setRegistry($container->get(Registry::class));
|
||||
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
391
administrator/components/com_finder/sql/install.mysql.sql
Normal file
391
administrator/components/com_finder/sql/install.mysql.sql
Normal file
@ -0,0 +1,391 @@
|
||||
--
|
||||
-- Table structure for table `#__finder_filters`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_filters` (
|
||||
`filter_id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`alias` varchar(255) NOT NULL,
|
||||
`state` tinyint NOT NULL DEFAULT 1,
|
||||
`created` datetime NOT NULL,
|
||||
`created_by` int unsigned NOT NULL DEFAULT 0,
|
||||
`created_by_alias` varchar(255) NOT NULL DEFAULT '',
|
||||
`modified` datetime NOT NULL,
|
||||
`modified_by` int unsigned NOT NULL DEFAULT 0,
|
||||
`checked_out` int unsigned NOT NULL DEFAULT 0,
|
||||
`checked_out_time` datetime,
|
||||
`map_count` int unsigned NOT NULL DEFAULT 0,
|
||||
`data` text,
|
||||
`params` mediumtext,
|
||||
PRIMARY KEY (`filter_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_links`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_links` (
|
||||
`link_id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`url` varchar(255) NOT NULL,
|
||||
`route` varchar(255) NOT NULL,
|
||||
`title` varchar(400) DEFAULT NULL,
|
||||
`description` text,
|
||||
`indexdate` datetime NOT NULL,
|
||||
`md5sum` varchar(32) DEFAULT NULL,
|
||||
`published` tinyint NOT NULL DEFAULT 1,
|
||||
`state` int NOT NULL DEFAULT 1,
|
||||
`access` int NOT NULL DEFAULT 0,
|
||||
`language` char(7) NOT NULL DEFAULT '',
|
||||
`publish_start_date` datetime,
|
||||
`publish_end_date` datetime,
|
||||
`start_date` datetime,
|
||||
`end_date` datetime,
|
||||
`list_price` double unsigned NOT NULL DEFAULT 0,
|
||||
`sale_price` double unsigned NOT NULL DEFAULT 0,
|
||||
`type_id` int NOT NULL,
|
||||
`object` mediumblob,
|
||||
PRIMARY KEY (`link_id`),
|
||||
KEY `idx_type` (`type_id`),
|
||||
KEY `idx_title` (`title`(100)),
|
||||
KEY `idx_md5` (`md5sum`),
|
||||
KEY `idx_url` (`url`(75)),
|
||||
KEY `idx_language` (`language`),
|
||||
KEY `idx_published_list` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`list_price`),
|
||||
KEY `idx_published_sale` (`published`,`state`,`access`,`publish_start_date`,`publish_end_date`,`sale_price`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_links_terms`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_links_terms` (
|
||||
`link_id` int unsigned NOT NULL,
|
||||
`term_id` int unsigned NOT NULL,
|
||||
`weight` float unsigned NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`link_id`,`term_id`),
|
||||
KEY `idx_term_weight` (`term_id`,`weight`),
|
||||
KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_logging`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_logging` (
|
||||
`searchterm` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`md5sum` VARCHAR(32) NOT NULL DEFAULT '',
|
||||
`query` BLOB NOT NULL,
|
||||
`hits` int NOT NULL DEFAULT 1,
|
||||
`results` int NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`md5sum`),
|
||||
INDEX `searchterm` (`searchterm`(191))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_taxonomy`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_taxonomy` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`parent_id` int UNSIGNED NOT NULL DEFAULT '0',
|
||||
`lft` int NOT NULL DEFAULT '0',
|
||||
`rgt` int NOT NULL DEFAULT '0',
|
||||
`level` int UNSIGNED NOT NULL DEFAULT '0',
|
||||
`path` VARCHAR(400) NOT NULL DEFAULT '',
|
||||
`title` VARCHAR(255) NOT NULL DEFAULT '',
|
||||
`alias` VARCHAR(400) NOT NULL DEFAULT '',
|
||||
`state` tinyint UNSIGNED NOT NULL DEFAULT '1',
|
||||
`access` tinyint UNSIGNED NOT NULL DEFAULT '1',
|
||||
`language` CHAR(7) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `idx_state` (`state`),
|
||||
INDEX `idx_access` (`access`),
|
||||
INDEX `idx_path` (`path`(100)),
|
||||
INDEX `idx_left_right` (`lft`, `rgt`),
|
||||
INDEX `idx_alias` (`alias`(100)),
|
||||
INDEX `idx_language` (`language`),
|
||||
INDEX `idx_parent_published` (`parent_id`, `state`, `access`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `#__finder_taxonomy`
|
||||
--
|
||||
|
||||
INSERT INTO `#__finder_taxonomy` (`id`, `parent_id`, `lft`, `rgt`, `level`, `path`, `title`, `alias`, `state`, `access`, `language`) VALUES
|
||||
(1, 0, 0, 1, 0, '', 'ROOT', 'root', 1, 1, '*');
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_taxonomy_map`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_taxonomy_map` (
|
||||
`link_id` int unsigned NOT NULL,
|
||||
`node_id` int unsigned NOT NULL,
|
||||
PRIMARY KEY (`link_id`,`node_id`),
|
||||
KEY `link_id` (`link_id`),
|
||||
KEY `node_id` (`node_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_terms`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_terms` (
|
||||
`term_id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`term` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
||||
`stem` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`common` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`phrase` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`weight` float unsigned NOT NULL DEFAULT 0,
|
||||
`soundex` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`links` int NOT NULL DEFAULT 0,
|
||||
`language` char(7) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`term_id`),
|
||||
UNIQUE KEY `idx_term_language` (`term`,`language`),
|
||||
KEY `idx_stem` (`stem`),
|
||||
KEY `idx_term_phrase` (`term`,`phrase`),
|
||||
KEY `idx_stem_phrase` (`stem`,`phrase`),
|
||||
KEY `idx_soundex_phrase` (`soundex`,`phrase`),
|
||||
KEY `idx_language` (`language`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_terms_common`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_terms_common` (
|
||||
`term` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`language` char(7) NOT NULL DEFAULT '',
|
||||
`custom` int NOT NULL DEFAULT '0',
|
||||
UNIQUE KEY `idx_term_language` (`term`,`language`),
|
||||
KEY `idx_lang` (`language`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `#__finder_terms_common`
|
||||
--
|
||||
|
||||
INSERT INTO `#__finder_terms_common` (`term`, `language`, `custom`) VALUES
|
||||
('i', 'en', 0),
|
||||
('me', 'en', 0),
|
||||
('my', 'en', 0),
|
||||
('myself', 'en', 0),
|
||||
('we', 'en', 0),
|
||||
('our', 'en', 0),
|
||||
('ours', 'en', 0),
|
||||
('ourselves', 'en', 0),
|
||||
('you', 'en', 0),
|
||||
('your', 'en', 0),
|
||||
('yours', 'en', 0),
|
||||
('yourself', 'en', 0),
|
||||
('yourselves', 'en', 0),
|
||||
('he', 'en', 0),
|
||||
('him', 'en', 0),
|
||||
('his', 'en', 0),
|
||||
('himself', 'en', 0),
|
||||
('she', 'en', 0),
|
||||
('her', 'en', 0),
|
||||
('hers', 'en', 0),
|
||||
('herself', 'en', 0),
|
||||
('it', 'en', 0),
|
||||
('its', 'en', 0),
|
||||
('itself', 'en', 0),
|
||||
('they', 'en', 0),
|
||||
('them', 'en', 0),
|
||||
('their', 'en', 0),
|
||||
('theirs', 'en', 0),
|
||||
('themselves', 'en', 0),
|
||||
('what', 'en', 0),
|
||||
('which', 'en', 0),
|
||||
('who', 'en', 0),
|
||||
('whom', 'en', 0),
|
||||
('this', 'en', 0),
|
||||
('that', 'en', 0),
|
||||
('these', 'en', 0),
|
||||
('those', 'en', 0),
|
||||
('am', 'en', 0),
|
||||
('is', 'en', 0),
|
||||
('are', 'en', 0),
|
||||
('was', 'en', 0),
|
||||
('were', 'en', 0),
|
||||
('be', 'en', 0),
|
||||
('been', 'en', 0),
|
||||
('being', 'en', 0),
|
||||
('have', 'en', 0),
|
||||
('has', 'en', 0),
|
||||
('had', 'en', 0),
|
||||
('having', 'en', 0),
|
||||
('do', 'en', 0),
|
||||
('does', 'en', 0),
|
||||
('did', 'en', 0),
|
||||
('doing', 'en', 0),
|
||||
('would', 'en', 0),
|
||||
('should', 'en', 0),
|
||||
('could', 'en', 0),
|
||||
('ought', 'en', 0),
|
||||
('i\'m', 'en', 0),
|
||||
('you\'re', 'en', 0),
|
||||
('he\'s', 'en', 0),
|
||||
('she\'s', 'en', 0),
|
||||
('it\'s', 'en', 0),
|
||||
('we\'re', 'en', 0),
|
||||
('they\'re', 'en', 0),
|
||||
('i\'ve', 'en', 0),
|
||||
('you\'ve', 'en', 0),
|
||||
('we\'ve', 'en', 0),
|
||||
('they\'ve', 'en', 0),
|
||||
('i\'d', 'en', 0),
|
||||
('you\'d', 'en', 0),
|
||||
('he\'d', 'en', 0),
|
||||
('she\'d', 'en', 0),
|
||||
('we\'d', 'en', 0),
|
||||
('they\'d', 'en', 0),
|
||||
('i\'ll', 'en', 0),
|
||||
('you\'ll', 'en', 0),
|
||||
('he\'ll', 'en', 0),
|
||||
('she\'ll', 'en', 0),
|
||||
('we\'ll', 'en', 0),
|
||||
('they\'ll', 'en', 0),
|
||||
('isn\'t', 'en', 0),
|
||||
('aren\'t', 'en', 0),
|
||||
('wasn\'t', 'en', 0),
|
||||
('weren\'t', 'en', 0),
|
||||
('hasn\'t', 'en', 0),
|
||||
('haven\'t', 'en', 0),
|
||||
('hadn\'t', 'en', 0),
|
||||
('doesn\'t', 'en', 0),
|
||||
('don\'t', 'en', 0),
|
||||
('didn\'t', 'en', 0),
|
||||
('won\'t', 'en', 0),
|
||||
('wouldn\'t', 'en', 0),
|
||||
('shan\'t', 'en', 0),
|
||||
('shouldn\'t', 'en', 0),
|
||||
('can\'t', 'en', 0),
|
||||
('cannot', 'en', 0),
|
||||
('couldn\'t', 'en', 0),
|
||||
('mustn\'t', 'en', 0),
|
||||
('let\'s', 'en', 0),
|
||||
('that\'s', 'en', 0),
|
||||
('who\'s', 'en', 0),
|
||||
('what\'s', 'en', 0),
|
||||
('here\'s', 'en', 0),
|
||||
('there\'s', 'en', 0),
|
||||
('when\'s', 'en', 0),
|
||||
('where\'s', 'en', 0),
|
||||
('why\'s', 'en', 0),
|
||||
('how\'s', 'en', 0),
|
||||
('a', 'en', 0),
|
||||
('an', 'en', 0),
|
||||
('the', 'en', 0),
|
||||
('and', 'en', 0),
|
||||
('but', 'en', 0),
|
||||
('if', 'en', 0),
|
||||
('or', 'en', 0),
|
||||
('because', 'en', 0),
|
||||
('as', 'en', 0),
|
||||
('until', 'en', 0),
|
||||
('while', 'en', 0),
|
||||
('of', 'en', 0),
|
||||
('at', 'en', 0),
|
||||
('by', 'en', 0),
|
||||
('for', 'en', 0),
|
||||
('with', 'en', 0),
|
||||
('about', 'en', 0),
|
||||
('against', 'en', 0),
|
||||
('between', 'en', 0),
|
||||
('into', 'en', 0),
|
||||
('through', 'en', 0),
|
||||
('during', 'en', 0),
|
||||
('before', 'en', 0),
|
||||
('after', 'en', 0),
|
||||
('above', 'en', 0),
|
||||
('below', 'en', 0),
|
||||
('to', 'en', 0),
|
||||
('from', 'en', 0),
|
||||
('up', 'en', 0),
|
||||
('down', 'en', 0),
|
||||
('in', 'en', 0),
|
||||
('out', 'en', 0),
|
||||
('on', 'en', 0),
|
||||
('off', 'en', 0),
|
||||
('over', 'en', 0),
|
||||
('under', 'en', 0),
|
||||
('again', 'en', 0),
|
||||
('further', 'en', 0),
|
||||
('then', 'en', 0),
|
||||
('once', 'en', 0),
|
||||
('here', 'en', 0),
|
||||
('there', 'en', 0),
|
||||
('when', 'en', 0),
|
||||
('where', 'en', 0),
|
||||
('why', 'en', 0),
|
||||
('how', 'en', 0),
|
||||
('all', 'en', 0),
|
||||
('any', 'en', 0),
|
||||
('both', 'en', 0),
|
||||
('each', 'en', 0),
|
||||
('few', 'en', 0),
|
||||
('more', 'en', 0),
|
||||
('most', 'en', 0),
|
||||
('other', 'en', 0),
|
||||
('some', 'en', 0),
|
||||
('such', 'en', 0),
|
||||
('no', 'en', 0),
|
||||
('nor', 'en', 0),
|
||||
('not', 'en', 0),
|
||||
('only', 'en', 0),
|
||||
('own', 'en', 0),
|
||||
('same', 'en', 0),
|
||||
('so', 'en', 0),
|
||||
('than', 'en', 0),
|
||||
('too', 'en', 0),
|
||||
('very', 'en', 0);
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_tokens`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_tokens` (
|
||||
`term` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
||||
`stem` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`common` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`phrase` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`weight` float unsigned NOT NULL DEFAULT 1,
|
||||
`context` tinyint unsigned NOT NULL DEFAULT 2,
|
||||
`language` char(7) NOT NULL DEFAULT '',
|
||||
KEY `idx_word` (`term`),
|
||||
KEY `idx_stem` (`stem`),
|
||||
KEY `idx_context` (`context`),
|
||||
KEY `idx_language` (`language`)
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_tokens_aggregate`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_tokens_aggregate` (
|
||||
`term_id` int unsigned NOT NULL,
|
||||
`term` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
||||
`stem` varchar(75) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',
|
||||
`common` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`phrase` tinyint unsigned NOT NULL DEFAULT 0,
|
||||
`term_weight` float unsigned NOT NULL DEFAULT 0,
|
||||
`context` tinyint unsigned NOT NULL DEFAULT 2,
|
||||
`context_weight` float unsigned NOT NULL DEFAULT 0,
|
||||
`total_weight` float unsigned NOT NULL DEFAULT 0,
|
||||
`language` char(7) NOT NULL DEFAULT '',
|
||||
KEY `token` (`term`),
|
||||
KEY `keyword_id` (`term_id`)
|
||||
) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_types`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__finder_types` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL,
|
||||
`mime` varchar(100) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `title` (`title`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
|
||||
455
administrator/components/com_finder/sql/install.postgresql.sql
Normal file
455
administrator/components/com_finder/sql/install.postgresql.sql
Normal file
@ -0,0 +1,455 @@
|
||||
--
|
||||
-- Table structure for table `#__finder_filters`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_filters" (
|
||||
"filter_id" serial NOT NULL,
|
||||
"title" varchar(255) NOT NULL,
|
||||
"alias" varchar(255) NOT NULL,
|
||||
"state" smallint DEFAULT 1 NOT NULL,
|
||||
"created" timestamp without time zone NOT NULL,
|
||||
"created_by" integer DEFAULT 0 NOT NULL,
|
||||
"created_by_alias" varchar(255) DEFAULT '' NOT NULL,
|
||||
"modified" timestamp without time zone NOT NULL,
|
||||
"modified_by" integer DEFAULT 0 NOT NULL,
|
||||
"checked_out" integer DEFAULT 0 NOT NULL,
|
||||
"checked_out_time" timestamp without time zone,
|
||||
"map_count" integer DEFAULT 0 NOT NULL,
|
||||
"data" text,
|
||||
"params" text,
|
||||
PRIMARY KEY ("filter_id")
|
||||
);
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_links`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_links" (
|
||||
"link_id" serial NOT NULL,
|
||||
"url" varchar(255) NOT NULL,
|
||||
"route" varchar(255) NOT NULL,
|
||||
"title" varchar(400) DEFAULT NULL,
|
||||
"description" text,
|
||||
"indexdate" timestamp without time zone NOT NULL,
|
||||
"md5sum" varchar(32) DEFAULT NULL,
|
||||
"published" smallint DEFAULT 1 NOT NULL,
|
||||
"state" integer DEFAULT 1 NOT NULL,
|
||||
"access" integer DEFAULT 0 NOT NULL,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL,
|
||||
"publish_start_date" timestamp without time zone,
|
||||
"publish_end_date" timestamp without time zone,
|
||||
"start_date" timestamp without time zone,
|
||||
"end_date" timestamp without time zone,
|
||||
"list_price" numeric(8,2) DEFAULT 0 NOT NULL,
|
||||
"sale_price" numeric(8,2) DEFAULT 0 NOT NULL,
|
||||
"type_id" bigint NOT NULL,
|
||||
"object" bytea,
|
||||
PRIMARY KEY ("link_id")
|
||||
);
|
||||
CREATE INDEX "#__finder_links_idx_type" on "#__finder_links" ("type_id");
|
||||
CREATE INDEX "#__finder_links_idx_title" on "#__finder_links" ("title");
|
||||
CREATE INDEX "#__finder_links_idx_md5" on "#__finder_links" ("md5sum");
|
||||
CREATE INDEX "#__finder_links_idx_language" on "#__finder_links" ("language");
|
||||
CREATE INDEX "#__finder_links_idx_url" on "#__finder_links" (substr(url,0,76));
|
||||
CREATE INDEX "#__finder_links_idx_published_list" on "#__finder_links" ("published", "state", "access", "publish_start_date", "publish_end_date", "list_price");
|
||||
CREATE INDEX "#__finder_links_idx_published_sale" on "#__finder_links" ("published", "state", "access", "publish_start_date", "publish_end_date", "sale_price");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_links_terms`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_links_terms" (
|
||||
"link_id" integer NOT NULL,
|
||||
"term_id" integer NOT NULL,
|
||||
"weight" numeric(8,2) DEFAULT 0 NOT NULL,
|
||||
PRIMARY KEY ("link_id", "term_id")
|
||||
);
|
||||
CREATE INDEX "#__finder_links_terms_idx_term_weight" on "#__finder_links_terms" ("term_id", "weight");
|
||||
CREATE INDEX "#__finder_links_terms_idx_link_term_weight" on "#__finder_links_terms" ("link_id", "term_id", "weight");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_logging`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_logging" (
|
||||
"searchterm" character varying(255) NOT NULL DEFAULT '',
|
||||
"md5sum" character varying(32) NOT NULL DEFAULT '',
|
||||
"query" bytea NOT NULL,
|
||||
"hits" integer NOT NULL DEFAULT 1,
|
||||
"results" integer NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY ("md5sum")
|
||||
);
|
||||
CREATE INDEX "#__finder_logging_idx_md5sum" on "#__finder_logging" ("md5sum");
|
||||
CREATE INDEX "#__finder_logging_idx_searchterm" on "#__finder_logging" ("searchterm");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_taxonomy`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_taxonomy" (
|
||||
"id" serial NOT NULL,
|
||||
"parent_id" integer DEFAULT 0 NOT NULL,
|
||||
"lft" integer DEFAULT 0 NOT NULL,
|
||||
"rgt" integer DEFAULT 0 NOT NULL,
|
||||
"level" integer DEFAULT 0 NOT NULL,
|
||||
"path" VARCHAR(400) NOT NULL DEFAULT '',
|
||||
"title" VARCHAR(255) NOT NULL DEFAULT '',
|
||||
"alias" VARCHAR(400) NOT NULL DEFAULT '',
|
||||
"state" smallint DEFAULT 1 NOT NULL,
|
||||
"access" smallint DEFAULT 1 NOT NULL,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
CREATE INDEX "#__finder_taxonomy_state" on "#__finder_taxonomy" ("state");
|
||||
CREATE INDEX "#__finder_taxonomy_access" on "#__finder_taxonomy" ("access");
|
||||
CREATE INDEX "#__finder_taxonomy_path" on "#__finder_taxonomy" ("path");
|
||||
CREATE INDEX "#__finder_taxonomy_lft_rgt" on "#__finder_taxonomy" ("lft", "rgt");
|
||||
CREATE INDEX "#__finder_taxonomy_alias" on "#__finder_taxonomy" ("alias");
|
||||
CREATE INDEX "#__finder_taxonomy_language" on "#__finder_taxonomy" ("language");
|
||||
CREATE INDEX "#__finder_taxonomy_idx_parent_published" on "#__finder_taxonomy" ("parent_id", "state", "access");
|
||||
|
||||
--
|
||||
-- Dumping data for table `#__finder_taxonomy`
|
||||
--
|
||||
|
||||
INSERT INTO "#__finder_taxonomy" ("id", "parent_id", "lft", "rgt", "level", "path", "title", "alias", "state", "access", "language") VALUES
|
||||
(1, 0, 0, 1, 0, '', 'ROOT', 'root', 1, 1, '*');
|
||||
|
||||
SELECT setval('#__finder_taxonomy_id_seq', 2, false);
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_taxonomy_map`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_taxonomy_map" (
|
||||
"link_id" integer NOT NULL,
|
||||
"node_id" integer NOT NULL,
|
||||
PRIMARY KEY ("link_id", "node_id")
|
||||
);
|
||||
CREATE INDEX "#__finder_taxonomy_map_link_id" on "#__finder_taxonomy_map" ("link_id");
|
||||
CREATE INDEX "#__finder_taxonomy_map_node_id" on "#__finder_taxonomy_map" ("node_id");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_terms`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_terms" (
|
||||
"term_id" serial NOT NULL,
|
||||
"term" varchar(75) NOT NULL,
|
||||
"stem" varchar(75) DEFAULT '' NOT NULL,
|
||||
"common" smallint DEFAULT 0 NOT NULL,
|
||||
"phrase" smallint DEFAULT 0 NOT NULL,
|
||||
"weight" numeric(8,2) DEFAULT 0 NOT NULL,
|
||||
"soundex" varchar(75) DEFAULT '' NOT NULL,
|
||||
"links" integer DEFAULT 0 NOT NULL,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY ("term_id"),
|
||||
CONSTRAINT "#__finder_terms_idx_term_language" UNIQUE ("term", "language")
|
||||
);
|
||||
CREATE INDEX "#__finder_terms_idx_term_phrase" on "#__finder_terms" ("term", "phrase");
|
||||
CREATE INDEX "#__finder_terms_idx_stem_phrase" on "#__finder_terms" ("stem", "phrase");
|
||||
CREATE INDEX "#__finder_terms_idx_soundex_phrase" on "#__finder_terms" ("soundex", "phrase");
|
||||
CREATE INDEX "#__finder_terms_idx_language" on "#__finder_terms" ("language");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_terms_common`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_terms_common" (
|
||||
"term" varchar(75) NOT NULL,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL,
|
||||
"custom" integer DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT "#__finder_terms_common_idx_term_language" UNIQUE ("term", "language")
|
||||
);
|
||||
CREATE INDEX "#__finder_terms_common_idx_lang" on "#__finder_terms_common" ("language");
|
||||
|
||||
--
|
||||
-- Dumping data for table `#__finder_terms_common`
|
||||
--
|
||||
|
||||
INSERT INTO "#__finder_terms_common" ("term", "language", "custom") VALUES
|
||||
('i', 'en', 0),
|
||||
('me', 'en', 0),
|
||||
('my', 'en', 0),
|
||||
('myself', 'en', 0),
|
||||
('we', 'en', 0),
|
||||
('our', 'en', 0),
|
||||
('ours', 'en', 0),
|
||||
('ourselves', 'en', 0),
|
||||
('you', 'en', 0),
|
||||
('your', 'en', 0),
|
||||
('yours', 'en', 0),
|
||||
('yourself', 'en', 0),
|
||||
('yourselves', 'en', 0),
|
||||
('he', 'en', 0),
|
||||
('him', 'en', 0),
|
||||
('his', 'en', 0),
|
||||
('himself', 'en', 0),
|
||||
('she', 'en', 0),
|
||||
('her', 'en', 0),
|
||||
('hers', 'en', 0),
|
||||
('herself', 'en', 0),
|
||||
('it', 'en', 0),
|
||||
('its', 'en', 0),
|
||||
('itself', 'en', 0),
|
||||
('they', 'en', 0),
|
||||
('them', 'en', 0),
|
||||
('their', 'en', 0),
|
||||
('theirs', 'en', 0),
|
||||
('themselves', 'en', 0),
|
||||
('what', 'en', 0),
|
||||
('which', 'en', 0),
|
||||
('who', 'en', 0),
|
||||
('whom', 'en', 0),
|
||||
('this', 'en', 0),
|
||||
('that', 'en', 0),
|
||||
('these', 'en', 0),
|
||||
('those', 'en', 0),
|
||||
('am', 'en', 0),
|
||||
('is', 'en', 0),
|
||||
('are', 'en', 0),
|
||||
('was', 'en', 0),
|
||||
('were', 'en', 0),
|
||||
('be', 'en', 0),
|
||||
('been', 'en', 0),
|
||||
('being', 'en', 0),
|
||||
('have', 'en', 0),
|
||||
('has', 'en', 0),
|
||||
('had', 'en', 0),
|
||||
('having', 'en', 0),
|
||||
('do', 'en', 0),
|
||||
('does', 'en', 0),
|
||||
('did', 'en', 0),
|
||||
('doing', 'en', 0),
|
||||
('would', 'en', 0),
|
||||
('should', 'en', 0),
|
||||
('could', 'en', 0),
|
||||
('ought', 'en', 0),
|
||||
('i''m', 'en', 0),
|
||||
('you''re', 'en', 0),
|
||||
('he''s', 'en', 0),
|
||||
('she''s', 'en', 0),
|
||||
('it''s', 'en', 0),
|
||||
('we''re', 'en', 0),
|
||||
('they''re', 'en', 0),
|
||||
('i''ve', 'en', 0),
|
||||
('you''ve', 'en', 0),
|
||||
('we''ve', 'en', 0),
|
||||
('they''ve', 'en', 0),
|
||||
('i''d', 'en', 0),
|
||||
('you''d', 'en', 0),
|
||||
('he''d', 'en', 0),
|
||||
('she''d', 'en', 0),
|
||||
('we''d', 'en', 0),
|
||||
('they''d', 'en', 0),
|
||||
('i''ll', 'en', 0),
|
||||
('you''ll', 'en', 0),
|
||||
('he''ll', 'en', 0),
|
||||
('she''ll', 'en', 0),
|
||||
('we''ll', 'en', 0),
|
||||
('they''ll', 'en', 0),
|
||||
('isn''t', 'en', 0),
|
||||
('aren''t', 'en', 0),
|
||||
('wasn''t', 'en', 0),
|
||||
('weren''t', 'en', 0),
|
||||
('hasn''t', 'en', 0),
|
||||
('haven''t', 'en', 0),
|
||||
('hadn''t', 'en', 0),
|
||||
('doesn''t', 'en', 0),
|
||||
('don''t', 'en', 0),
|
||||
('didn''t', 'en', 0),
|
||||
('won''t', 'en', 0),
|
||||
('wouldn''t', 'en', 0),
|
||||
('shan''t', 'en', 0),
|
||||
('shouldn''t', 'en', 0),
|
||||
('can''t', 'en', 0),
|
||||
('cannot', 'en', 0),
|
||||
('couldn''t', 'en', 0),
|
||||
('mustn''t', 'en', 0),
|
||||
('let''s', 'en', 0),
|
||||
('that''s', 'en', 0),
|
||||
('who''s', 'en', 0),
|
||||
('what''s', 'en', 0),
|
||||
('here''s', 'en', 0),
|
||||
('there''s', 'en', 0),
|
||||
('when''s', 'en', 0),
|
||||
('where''s', 'en', 0),
|
||||
('why''s', 'en', 0),
|
||||
('how''s', 'en', 0),
|
||||
('a', 'en', 0),
|
||||
('an', 'en', 0),
|
||||
('the', 'en', 0),
|
||||
('and', 'en', 0),
|
||||
('but', 'en', 0),
|
||||
('if', 'en', 0),
|
||||
('or', 'en', 0),
|
||||
('because', 'en', 0),
|
||||
('as', 'en', 0),
|
||||
('until', 'en', 0),
|
||||
('while', 'en', 0),
|
||||
('of', 'en', 0),
|
||||
('at', 'en', 0),
|
||||
('by', 'en', 0),
|
||||
('for', 'en', 0),
|
||||
('with', 'en', 0),
|
||||
('about', 'en', 0),
|
||||
('against', 'en', 0),
|
||||
('between', 'en', 0),
|
||||
('into', 'en', 0),
|
||||
('through', 'en', 0),
|
||||
('during', 'en', 0),
|
||||
('before', 'en', 0),
|
||||
('after', 'en', 0),
|
||||
('above', 'en', 0),
|
||||
('below', 'en', 0),
|
||||
('to', 'en', 0),
|
||||
('from', 'en', 0),
|
||||
('up', 'en', 0),
|
||||
('down', 'en', 0),
|
||||
('in', 'en', 0),
|
||||
('out', 'en', 0),
|
||||
('on', 'en', 0),
|
||||
('off', 'en', 0),
|
||||
('over', 'en', 0),
|
||||
('under', 'en', 0),
|
||||
('again', 'en', 0),
|
||||
('further', 'en', 0),
|
||||
('then', 'en', 0),
|
||||
('once', 'en', 0),
|
||||
('here', 'en', 0),
|
||||
('there', 'en', 0),
|
||||
('when', 'en', 0),
|
||||
('where', 'en', 0),
|
||||
('why', 'en', 0),
|
||||
('how', 'en', 0),
|
||||
('all', 'en', 0),
|
||||
('any', 'en', 0),
|
||||
('both', 'en', 0),
|
||||
('each', 'en', 0),
|
||||
('few', 'en', 0),
|
||||
('more', 'en', 0),
|
||||
('most', 'en', 0),
|
||||
('other', 'en', 0),
|
||||
('some', 'en', 0),
|
||||
('such', 'en', 0),
|
||||
('no', 'en', 0),
|
||||
('nor', 'en', 0),
|
||||
('not', 'en', 0),
|
||||
('only', 'en', 0),
|
||||
('own', 'en', 0),
|
||||
('same', 'en', 0),
|
||||
('so', 'en', 0),
|
||||
('than', 'en', 0),
|
||||
('too', 'en', 0),
|
||||
('very', 'en', 0);
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_tokens`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_tokens" (
|
||||
"term" varchar(75) NOT NULL,
|
||||
"stem" varchar(75) DEFAULT '' NOT NULL,
|
||||
"common" smallint DEFAULT 0 NOT NULL,
|
||||
"phrase" smallint DEFAULT 0 NOT NULL,
|
||||
"weight" numeric(8,2) DEFAULT 1 NOT NULL,
|
||||
"context" smallint DEFAULT 2 NOT NULL,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL
|
||||
);
|
||||
CREATE INDEX "#__finder_tokens_idx_word" on "#__finder_tokens" ("term");
|
||||
CREATE INDEX "#__finder_tokens_idx_stem" on "#__finder_tokens" ("stem");
|
||||
CREATE INDEX "#__finder_tokens_idx_context" on "#__finder_tokens" ("context");
|
||||
CREATE INDEX "#__finder_tokens_idx_language" on "#__finder_tokens" ("language");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_tokens_aggregate`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_tokens_aggregate" (
|
||||
"term_id" integer NOT NULL,
|
||||
"term" varchar(75) NOT NULL,
|
||||
"stem" varchar(75) DEFAULT '' NOT NULL,
|
||||
"common" smallint DEFAULT 0 NOT NULL,
|
||||
"phrase" smallint DEFAULT 0 NOT NULL,
|
||||
"term_weight" numeric(8,2) NOT NULL DEFAULT 0,
|
||||
"context" smallint DEFAULT 2 NOT NULL,
|
||||
"context_weight" numeric(8,2) NOT NULL DEFAULT 0,
|
||||
"total_weight" numeric(8,2) NOT NULL DEFAULT 0,
|
||||
"language" varchar(7) DEFAULT '' NOT NULL
|
||||
);
|
||||
CREATE INDEX "#__finder_tokens_aggregate_token" on "#__finder_tokens_aggregate" ("term");
|
||||
CREATE INDEX "_#__finder_tokens_aggregate_keyword_id" on "#__finder_tokens_aggregate" ("term_id");
|
||||
|
||||
--
|
||||
-- Table structure for table `#__finder_types`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "#__finder_types" (
|
||||
"id" serial NOT NULL,
|
||||
"title" varchar(100) NOT NULL,
|
||||
"mime" varchar(100) DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY ("id"),
|
||||
CONSTRAINT "#__finder_types_title" UNIQUE ("title")
|
||||
);
|
||||
|
||||
--
|
||||
-- Here is SOUNDEX replacement for those who can't enable fuzzystrmatch module
|
||||
-- from contrib folder.
|
||||
-- This function comes from https://wiki.postgresql.org/wiki/Soundex
|
||||
-- and is distributed with GPL license.
|
||||
-- Thanks to its author, Marti Raudsepp, that published this piece of code.
|
||||
--
|
||||
|
||||
CREATE OR REPLACE FUNCTION soundex(input text) RETURNS text
|
||||
IMMUTABLE STRICT COST 500 LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
soundex text = '';
|
||||
char text;
|
||||
symbol text;
|
||||
last_symbol text = '';
|
||||
pos int = 1;
|
||||
BEGIN
|
||||
WHILE length(soundex) < 4 LOOP
|
||||
char = upper(substr(input, pos, 1));
|
||||
pos = pos + 1;
|
||||
CASE char
|
||||
WHEN '' THEN
|
||||
-- End of input string
|
||||
IF soundex = '' THEN
|
||||
RETURN '';
|
||||
ELSE
|
||||
RETURN rpad(soundex, 4, '0');
|
||||
END IF;
|
||||
WHEN 'B', 'F', 'P', 'V' THEN
|
||||
symbol = '1';
|
||||
WHEN 'C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z' THEN
|
||||
symbol = '2';
|
||||
WHEN 'D', 'T' THEN
|
||||
symbol = '3';
|
||||
WHEN 'L' THEN
|
||||
symbol = '4';
|
||||
WHEN 'M', 'N' THEN
|
||||
symbol = '5';
|
||||
WHEN 'R' THEN
|
||||
symbol = '6';
|
||||
ELSE
|
||||
-- Not a consonant; no output, but next similar consonant will be re-recorded
|
||||
symbol = '';
|
||||
END CASE;
|
||||
|
||||
IF soundex = '' THEN
|
||||
-- First character; only accept strictly English ASCII characters
|
||||
IF char ~>=~ 'A' AND char ~<=~ 'Z' THEN
|
||||
soundex = char;
|
||||
last_symbol = symbol;
|
||||
END IF;
|
||||
ELSIF last_symbol != symbol THEN
|
||||
soundex = soundex || symbol;
|
||||
last_symbol = symbol;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
RETURN soundex;
|
||||
END;
|
||||
$$;
|
||||
11
administrator/components/com_finder/sql/uninstall.mysql.sql
Normal file
11
administrator/components/com_finder/sql/uninstall.mysql.sql
Normal file
@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS `#__finder_filters`;
|
||||
DROP TABLE IF EXISTS `#__finder_links`;
|
||||
DROP TABLE IF EXISTS `#__finder_links_terms`;
|
||||
DROP TABLE IF EXISTS `#__finder_logging`;
|
||||
DROP TABLE IF EXISTS `#__finder_taxonomy`;
|
||||
DROP TABLE IF EXISTS `#__finder_taxonomy_map`;
|
||||
DROP TABLE IF EXISTS `#__finder_terms`;
|
||||
DROP TABLE IF EXISTS `#__finder_terms_common`;
|
||||
DROP TABLE IF EXISTS `#__finder_tokens`;
|
||||
DROP TABLE IF EXISTS `#__finder_tokens_aggregate`;
|
||||
DROP TABLE IF EXISTS `#__finder_types`;
|
||||
@ -0,0 +1,11 @@
|
||||
DROP TABLE IF EXISTS "#__finder_filters";
|
||||
DROP TABLE IF EXISTS "#__finder_links";
|
||||
DROP TABLE IF EXISTS "#__finder_links_terms";
|
||||
DROP TABLE IF EXISTS "#__finder_logging";
|
||||
DROP TABLE IF EXISTS "#__finder_taxonomy";
|
||||
DROP TABLE IF EXISTS "#__finder_taxonomy_map";
|
||||
DROP TABLE IF EXISTS "#__finder_terms";
|
||||
DROP TABLE IF EXISTS "#__finder_terms_common";
|
||||
DROP TABLE IF EXISTS "#__finder_tokens";
|
||||
DROP TABLE IF EXISTS "#__finder_tokens_aggregate";
|
||||
DROP TABLE IF EXISTS "#__finder_types";
|
||||
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Finder\Administrator\Helper\FinderHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Base controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The default view.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $default_view = 'index';
|
||||
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param boolean $cachable If true, the view output will be cached
|
||||
* @param array $urlparams An array of safe URL parameters and their variable types
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return static|boolean A Controller object to support chaining or false on failure.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = [])
|
||||
{
|
||||
$view = $this->input->get('view', 'index', 'word');
|
||||
$layout = $this->input->get('layout', 'index', 'word');
|
||||
$filterId = $this->input->get('filter_id', null, 'int');
|
||||
|
||||
if ($view === 'index') {
|
||||
$pluginEnabled = PluginHelper::isEnabled('content', 'finder');
|
||||
|
||||
if (!$pluginEnabled) {
|
||||
$finderPluginId = FinderHelper::getFinderPluginId();
|
||||
$link = HTMLHelper::_(
|
||||
'link',
|
||||
'#plugin' . $finderPluginId . 'Modal',
|
||||
Text::_('COM_FINDER_CONTENT_PLUGIN'),
|
||||
'class="alert-link" data-bs-toggle="modal" id="title-' . $finderPluginId . '"'
|
||||
);
|
||||
$this->app->enqueueMessage(Text::sprintf('COM_FINDER_INDEX_PLUGIN_CONTENT_NOT_ENABLED_LINK', $link), 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Check for edit form.
|
||||
if ($view === 'filter' && $layout === 'edit' && !$this->checkEditId('com_finder.edit.filter', $filterId)) {
|
||||
// Somehow the person just went to the form - we don't allow that.
|
||||
if (!\count($this->app->getMessageQueue())) {
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $filterId), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_finder&view=filters', false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::display();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Indexer controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FilterController extends FormController
|
||||
{
|
||||
/**
|
||||
* Method to save a record.
|
||||
*
|
||||
* @param string $key The name of the primary key of the URL variable.
|
||||
* @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions).
|
||||
*
|
||||
* @return boolean True if successful, false otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function save($key = null, $urlVar = null)
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
/** @var \Joomla\Component\Finder\Administrator\Model\FilterModel $model */
|
||||
$model = $this->getModel();
|
||||
$table = $model->getTable();
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
$checkin = $table->hasField('checked_out');
|
||||
$context = "$this->option.edit.$this->context";
|
||||
$task = $this->getTask();
|
||||
|
||||
// Determine the name of the primary key for the data.
|
||||
if (empty($key)) {
|
||||
$key = $table->getKeyName();
|
||||
}
|
||||
|
||||
// To avoid data collisions the urlVar may be different from the primary key.
|
||||
if (empty($urlVar)) {
|
||||
$urlVar = $key;
|
||||
}
|
||||
|
||||
$recordId = $this->input->get($urlVar, '', 'int');
|
||||
|
||||
if (!$this->checkEditId($context, $recordId)) {
|
||||
// Somehow the person just went to the form and tried to save it. We don't allow that.
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $recordId), 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Populate the row id from the session.
|
||||
$data[$key] = $recordId;
|
||||
|
||||
// The save2copy task needs to be handled slightly differently.
|
||||
if ($task === 'save2copy') {
|
||||
// Check-in the original row.
|
||||
if ($checkin && $model->checkin($data[$key]) === false) {
|
||||
// Check-in failed. Go back to the item and display a notice.
|
||||
if (!\count($this->app->getMessageQueue())) {
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $urlVar));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the ID and then treat the request as for Apply.
|
||||
$data[$key] = 0;
|
||||
$task = 'apply';
|
||||
}
|
||||
|
||||
// Access check.
|
||||
if (!$this->allowSave($data, $key)) {
|
||||
$this->setMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the posted data.
|
||||
// Sometimes the form needs some posted data, such as for plugins and modules.
|
||||
$form = $model->getForm($data, false);
|
||||
|
||||
if (!$form) {
|
||||
$this->app->enqueueMessage($model->getError(), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test whether the data is valid.
|
||||
$validData = $model->validate($form, $data);
|
||||
|
||||
// Check for validation errors.
|
||||
if ($validData === false) {
|
||||
// Get the validation messages.
|
||||
$errors = $model->getErrors();
|
||||
|
||||
// Push up to three validation messages out to the user.
|
||||
for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) {
|
||||
if ($errors[$i] instanceof \Exception) {
|
||||
$this->app->enqueueMessage($errors[$i]->getMessage(), 'warning');
|
||||
} else {
|
||||
$this->app->enqueueMessage($errors[$i], 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Save the data in the session.
|
||||
$this->app->setUserState($context . '.data', $data);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setRedirect(
|
||||
Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get and sanitize the filter data.
|
||||
$validData['data'] = $this->input->post->get('t', [], 'array');
|
||||
$validData['data'] = array_unique($validData['data']);
|
||||
$validData['data'] = ArrayHelper::toInteger($validData['data']);
|
||||
|
||||
// Remove any values of zero.
|
||||
if (array_search(0, $validData['data'], true)) {
|
||||
unset($validData['data'][array_search(0, $validData['data'], true)]);
|
||||
}
|
||||
|
||||
// Attempt to save the data.
|
||||
if (!$model->save($validData)) {
|
||||
// Save the data in the session.
|
||||
$this->app->setUserState($context . '.data', $validData);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
|
||||
$this->setRedirect(
|
||||
Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save succeeded, so check-in the record.
|
||||
if ($checkin && $model->checkin($validData[$key]) === false) {
|
||||
// Save the data in the session.
|
||||
$this->app->setUserState($context . '.data', $validData);
|
||||
|
||||
// Check-in failed, so go back to the record and display a notice.
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error');
|
||||
$this->setRedirect('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setMessage(
|
||||
Text::_(
|
||||
($this->app->getLanguage()->hasKey($this->text_prefix . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
|
||||
? $this->text_prefix : 'JLIB_APPLICATION') . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
|
||||
)
|
||||
);
|
||||
|
||||
// Redirect the user and adjust session state based on the chosen task.
|
||||
switch ($task) {
|
||||
case 'apply':
|
||||
// Set the record data in the session.
|
||||
$recordId = $model->getState($this->context . '.id');
|
||||
$this->holdEditId($context, $recordId);
|
||||
$this->app->setUserState($context . '.data', null);
|
||||
$model->checkout($recordId);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setRedirect(
|
||||
Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($recordId, $key), false)
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'save2new':
|
||||
// Clear the record id and data from the session.
|
||||
$this->releaseEditId($context, $recordId);
|
||||
$this->app->setUserState($context . '.data', null);
|
||||
|
||||
// Redirect back to the edit screen.
|
||||
$this->setRedirect(
|
||||
Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend(null, $key), false)
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Clear the record id and data from the session.
|
||||
$this->releaseEditId($context, $recordId);
|
||||
$this->app->setUserState($context . '.data', null);
|
||||
|
||||
// Redirect to the list screen.
|
||||
$this->setRedirect(
|
||||
Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false)
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Invoke the postSave method to allow for the child class to access the model.
|
||||
$this->postSaveHook($model, $validData);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filters controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FiltersController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $text_prefix = 'COM_FINDER_FILTERS';
|
||||
|
||||
/**
|
||||
* Method to get a model object, loading it if required.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getModel($name = 'Filter', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Event\Finder\GarbageCollectionEvent;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Indexer;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Index controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class IndexController extends AdminController
|
||||
{
|
||||
/**
|
||||
* Method to get a model object, loading it if required.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getModel($name = 'Index', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to optimise the index by removing orphaned entries.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function optimise()
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
|
||||
// Optimise the index by first running the garbage collection
|
||||
PluginHelper::importPlugin('finder', null, true, $dispatcher);
|
||||
$dispatcher->dispatch('onFinderGarbageCollection', new GarbageCollectionEvent('onFinderGarbageCollection', []));
|
||||
|
||||
// Now run the optimisation method from the indexer
|
||||
$indexer = new Indexer();
|
||||
$indexer->optimize();
|
||||
|
||||
$message = Text::_('COM_FINDER_INDEX_OPTIMISE_FINISHED');
|
||||
$this->setRedirect('index.php?option=com_finder&view=index', $message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to purge all indexed links from the database.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
// Remove the script time limit.
|
||||
if (\function_exists('set_time_limit')) {
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
||||
/** @var \Joomla\Component\Finder\Administrator\Model\IndexModel $model */
|
||||
$model = $this->getModel('Index', 'Administrator');
|
||||
|
||||
// Attempt to purge the index.
|
||||
$return = $model->purge();
|
||||
|
||||
if (!$return) {
|
||||
$message = Text::_('COM_FINDER_INDEX_PURGE_FAILED', $model->getError());
|
||||
$this->setRedirect('index.php?option=com_finder&view=index', $message);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$message = Text::_('COM_FINDER_INDEX_PURGE_SUCCESS');
|
||||
$this->setRedirect('index.php?option=com_finder&view=index', $message);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,421 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Event\Finder\BeforeIndexEvent;
|
||||
use Joomla\CMS\Event\Finder\BuildIndexEvent;
|
||||
use Joomla\CMS\Event\Finder\StartIndexEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Adapter;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\DebugAdapter;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\DebugIndexer;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Indexer;
|
||||
use Joomla\Component\Finder\Administrator\Response\Response;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Indexer controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class IndexerController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to start the indexer.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
// Check for a valid token. If invalid, send a 403 with the error message.
|
||||
if (!Session::checkToken('request')) {
|
||||
static::sendResponse(new \Exception(Text::_('JINVALID_TOKEN_NOTICE'), 403));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$dispatcher = $this->getDispatcher();
|
||||
|
||||
if ($params->get('enable_logging', '0')) {
|
||||
$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
|
||||
$options['text_file'] = 'indexer.php';
|
||||
Log::addLogger($options);
|
||||
}
|
||||
|
||||
// Log the start
|
||||
try {
|
||||
Log::add('Starting the indexer', Log::INFO);
|
||||
} catch (\RuntimeException $exception) {
|
||||
// Informational log only
|
||||
}
|
||||
|
||||
// We don't want this form to be cached.
|
||||
$this->app->allowCache(false);
|
||||
|
||||
// Put in a buffer to silence noise.
|
||||
ob_start();
|
||||
|
||||
// Reset the indexer state.
|
||||
Indexer::resetState();
|
||||
|
||||
// Import the finder plugins.
|
||||
PluginHelper::importPlugin('finder', null, true, $dispatcher);
|
||||
|
||||
// Add the indexer language to \JS
|
||||
Text::script('COM_FINDER_AN_ERROR_HAS_OCCURRED');
|
||||
Text::script('COM_FINDER_NO_ERROR_RETURNED');
|
||||
|
||||
// Start the indexer.
|
||||
try {
|
||||
// Trigger the onStartIndex event.
|
||||
$dispatcher->dispatch('onStartIndex', new StartIndexEvent('onStartIndex', []));
|
||||
|
||||
// Get the indexer state.
|
||||
$state = Indexer::getState();
|
||||
$state->start = 1;
|
||||
|
||||
$output = ob_get_contents();
|
||||
|
||||
if ($output) {
|
||||
throw new \Exception(Text::_('COM_FINDER_AN_ERROR_HAS_OCCURRED'));
|
||||
}
|
||||
|
||||
// Send the response.
|
||||
static::sendResponse($state);
|
||||
} catch (\Exception $e) {
|
||||
// Catch an exception and return the response.
|
||||
static::sendResponse($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to run the next batch of content through the indexer.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function batch()
|
||||
{
|
||||
// Check for a valid token. If invalid, send a 403 with the error message.
|
||||
if (!Session::checkToken('request')) {
|
||||
static::sendResponse(new \Exception(Text::_('JINVALID_TOKEN_NOTICE'), 403));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$dispatcher = $this->getDispatcher();
|
||||
|
||||
if ($params->get('enable_logging', '0')) {
|
||||
$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
|
||||
$options['text_file'] = 'indexer.php';
|
||||
Log::addLogger($options);
|
||||
}
|
||||
|
||||
// Log the start
|
||||
try {
|
||||
Log::add('Starting the indexer batch process', Log::INFO);
|
||||
} catch (\RuntimeException $exception) {
|
||||
// Informational log only
|
||||
}
|
||||
|
||||
// We don't want this form to be cached.
|
||||
$this->app->allowCache(false);
|
||||
|
||||
// Put in a buffer to silence noise.
|
||||
ob_start();
|
||||
|
||||
// Remove the script time limit.
|
||||
if (\function_exists('set_time_limit')) {
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
||||
// Get the indexer state.
|
||||
$state = Indexer::getState();
|
||||
|
||||
// Reset the batch offset.
|
||||
$state->batchOffset = 0;
|
||||
|
||||
// Update the indexer state.
|
||||
Indexer::setState($state);
|
||||
|
||||
// Import the finder plugins.
|
||||
PluginHelper::importPlugin('finder', null, true, $dispatcher);
|
||||
|
||||
/*
|
||||
* We are going to swap out the raw document object with an HTML document
|
||||
* in order to work around some plugins that don't do proper environment
|
||||
* checks before trying to use HTML document functions.
|
||||
*/
|
||||
$lang = $this->app->getLanguage();
|
||||
|
||||
// Get the document properties.
|
||||
$attributes = [
|
||||
'charset' => 'utf-8',
|
||||
'lineend' => 'unix',
|
||||
'tab' => ' ',
|
||||
'language' => $lang->getTag(),
|
||||
'direction' => $lang->isRtl() ? 'rtl' : 'ltr',
|
||||
];
|
||||
|
||||
// Start the indexer.
|
||||
try {
|
||||
// Trigger the onBeforeIndex event.
|
||||
$dispatcher->dispatch('onBeforeIndex', new BeforeIndexEvent('onBeforeIndex', []));
|
||||
|
||||
// Trigger the onBuildIndex event.
|
||||
$dispatcher->dispatch('onBuildIndex', new BuildIndexEvent('onBuildIndex', []));
|
||||
|
||||
// Get the indexer state.
|
||||
$state = Indexer::getState();
|
||||
$state->start = 0;
|
||||
$state->complete = 0;
|
||||
|
||||
// Log batch completion and memory high-water mark.
|
||||
try {
|
||||
Log::add('Batch completed, peak memory usage: ' . number_format(memory_get_peak_usage(true)) . ' bytes', Log::INFO);
|
||||
} catch (\RuntimeException $exception) {
|
||||
// Informational log only
|
||||
}
|
||||
|
||||
$output = ob_get_contents();
|
||||
|
||||
if ($output) {
|
||||
throw new \Exception(Text::_('COM_FINDER_INDEXER_ERROR_PLUGIN_FAILURE'));
|
||||
}
|
||||
|
||||
// Send the response.
|
||||
static::sendResponse($state);
|
||||
} catch (\Exception $e) {
|
||||
// Catch an exception and return the response.
|
||||
// Send the response.
|
||||
static::sendResponse($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to optimize the index and perform any necessary cleanup.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function optimize()
|
||||
{
|
||||
// Check for a valid token. If invalid, send a 403 with the error message.
|
||||
if (!Session::checkToken('request')) {
|
||||
static::sendResponse(new \Exception(Text::_('JINVALID_TOKEN_NOTICE'), 403));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't want this form to be cached.
|
||||
$this->app->allowCache(false);
|
||||
|
||||
// Put in a buffer to silence noise.
|
||||
ob_start();
|
||||
|
||||
// Import the finder plugins.
|
||||
PluginHelper::importPlugin('finder', null, true, $this->getDispatcher());
|
||||
|
||||
try {
|
||||
// Optimize the index
|
||||
$indexer = new Indexer();
|
||||
$indexer->optimize();
|
||||
|
||||
// Get the indexer state.
|
||||
$state = Indexer::getState();
|
||||
$state->start = 0;
|
||||
$state->complete = 1;
|
||||
|
||||
$output = ob_get_contents();
|
||||
|
||||
if ($output) {
|
||||
throw new \Exception(Text::_('COM_FINDER_AN_ERROR_HAS_OCCURRED'));
|
||||
}
|
||||
|
||||
// Send the response.
|
||||
static::sendResponse($state);
|
||||
} catch (\Exception $e) {
|
||||
// Catch an exception and return the response.
|
||||
static::sendResponse($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle a send a \JSON response. The body parameter
|
||||
* can be an \Exception object for when an error has occurred or
|
||||
* a CMSObject for a good response.
|
||||
*
|
||||
* @param \Joomla\CMS\Object\CMSObject|\Exception $data CMSObject on success, \Exception on error. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function sendResponse($data = null)
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
|
||||
if ($params->get('enable_logging', '0')) {
|
||||
$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
|
||||
$options['text_file'] = 'indexer.php';
|
||||
Log::addLogger($options);
|
||||
}
|
||||
|
||||
// Send the assigned error code if we are catching an exception.
|
||||
if ($data instanceof \Exception) {
|
||||
try {
|
||||
Log::add($data->getMessage(), Log::ERROR);
|
||||
} catch (\RuntimeException $exception) {
|
||||
// Informational log only
|
||||
}
|
||||
|
||||
$app->setHeader('status', $data->getCode());
|
||||
}
|
||||
|
||||
// Create the response object.
|
||||
$response = new Response($data);
|
||||
|
||||
if (\JDEBUG) {
|
||||
// Add the buffer and memory usage
|
||||
$response->buffer = ob_get_contents();
|
||||
$response->memory = memory_get_usage(true);
|
||||
}
|
||||
ob_clean();
|
||||
|
||||
// Send the JSON response.
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to call a specific indexing plugin and return debug info
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @internal
|
||||
*/
|
||||
public function debug()
|
||||
{
|
||||
// Check for a valid token. If invalid, send a 403 with the error message.
|
||||
if (!Session::checkToken('request')) {
|
||||
static::sendResponse(new \Exception(Text::_('JINVALID_TOKEN_NOTICE'), 403));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't want this form to be cached.
|
||||
$this->app->allowCache(false);
|
||||
|
||||
// Put in a buffer to silence noise.
|
||||
ob_start();
|
||||
|
||||
// Remove the script time limit.
|
||||
@set_time_limit(0);
|
||||
|
||||
// Get the indexer state.
|
||||
Indexer::resetState();
|
||||
$state = Indexer::getState();
|
||||
|
||||
// Reset the batch offset.
|
||||
$state->batchOffset = 0;
|
||||
|
||||
// Update the indexer state.
|
||||
Indexer::setState($state);
|
||||
|
||||
// Start the indexer.
|
||||
try {
|
||||
// Import the finder plugins.
|
||||
class_alias(DebugAdapter::class, Adapter::class);
|
||||
$plugin = $this->app->bootPlugin($this->app->getInput()->get('plugin'), 'finder');
|
||||
$plugin->setIndexer(new DebugIndexer());
|
||||
$plugin->debug($this->app->getInput()->get('id'));
|
||||
|
||||
$output = '';
|
||||
|
||||
// Create list of attributes
|
||||
$output .= '<fieldset><legend>' . Text::_('COM_FINDER_INDEXER_FIELDSET_ATTRIBUTES') . '</legend>';
|
||||
$output .= '<dl class="row">';
|
||||
|
||||
foreach (DebugIndexer::$item as $key => $value) {
|
||||
$output .= '<dt class="col-sm-2">' . $key . '</dt><dd class="col-sm-10">' . $value . '</dd>';
|
||||
}
|
||||
|
||||
$output .= '</dl>';
|
||||
$output .= '</fieldset>';
|
||||
|
||||
$output .= '<fieldset><legend>' . Text::_('COM_FINDER_INDEXER_FIELDSET_ELEMENTS') . '</legend>';
|
||||
$output .= '<dl class="row">';
|
||||
|
||||
foreach (DebugIndexer::$item->getElements() as $key => $element) {
|
||||
$output .= '<dt class="col-sm-2">' . $key . '</dt><dd class="col-sm-10">' . $element . '</dd>';
|
||||
}
|
||||
|
||||
$output .= '</dl>';
|
||||
$output .= '</fieldset>';
|
||||
|
||||
$output .= '<fieldset><legend>' . Text::_('COM_FINDER_INDEXER_FIELDSET_INSTRUCTIONS') . '</legend>';
|
||||
$output .= '<dl class="row">';
|
||||
$contexts = [
|
||||
1 => 'Title context',
|
||||
2 => 'Text context',
|
||||
3 => 'Meta context',
|
||||
4 => 'Path context',
|
||||
5 => 'Misc context',
|
||||
];
|
||||
|
||||
foreach (DebugIndexer::$item->getInstructions() as $key => $element) {
|
||||
$output .= '<dt class="col-sm-2">' . $contexts[$key] . '</dt><dd class="col-sm-10">' . json_encode($element) . '</dd>';
|
||||
}
|
||||
|
||||
$output .= '</dl>';
|
||||
$output .= '</fieldset>';
|
||||
|
||||
$output .= '<fieldset><legend>' . Text::_('COM_FINDER_INDEXER_FIELDSET_TAXONOMIES') . '</legend>';
|
||||
$output .= '<dl class="row">';
|
||||
|
||||
foreach (DebugIndexer::$item->getTaxonomy() as $key => $element) {
|
||||
$output .= '<dt class="col-sm-2">' . $key . '</dt><dd class="col-sm-10">' . json_encode($element) . '</dd>';
|
||||
}
|
||||
|
||||
$output .= '</dl>';
|
||||
$output .= '</fieldset>';
|
||||
|
||||
// Get the indexer state.
|
||||
$state = Indexer::getState();
|
||||
$state->start = 0;
|
||||
$state->complete = 0;
|
||||
$state->rendered = $output;
|
||||
|
||||
echo json_encode($state);
|
||||
} catch (\Exception $e) {
|
||||
// Catch an exception and return the response.
|
||||
// Send the response.
|
||||
static::sendResponse($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Maps controller class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class MapsController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $text_prefix = 'COM_FINDER_MAPS';
|
||||
|
||||
/**
|
||||
* Method to get a model object, loading it if required.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getModel($name = 'Maps', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Methods supporting a list of search terms.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class SearchesController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to reset the search log table.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));
|
||||
|
||||
$model = $this->getModel('Searches');
|
||||
|
||||
if (!$model->reset()) {
|
||||
$this->app->enqueueMessage($model->getError(), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect('index.php?option=com_finder&view=searches');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Extension;
|
||||
|
||||
use Joomla\CMS\Component\Router\RouterServiceInterface;
|
||||
use Joomla\CMS\Component\Router\RouterServiceTrait;
|
||||
use Joomla\CMS\Extension\BootableExtensionInterface;
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
use Joomla\CMS\HTML\HTMLRegistryAwareTrait;
|
||||
use Joomla\Component\Finder\Administrator\Service\HTML\Filter;
|
||||
use Joomla\Component\Finder\Administrator\Service\HTML\Finder;
|
||||
use Joomla\Component\Finder\Administrator\Service\HTML\Query;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Component class for com_finder
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class FinderComponent extends MVCComponent implements BootableExtensionInterface, RouterServiceInterface
|
||||
{
|
||||
use RouterServiceTrait;
|
||||
use HTMLRegistryAwareTrait;
|
||||
|
||||
/**
|
||||
* Booting the extension. This is the function to set up the environment of the extension like
|
||||
* registering new class loaders, etc.
|
||||
*
|
||||
* If required, some initial set up can be done from services of the container, eg.
|
||||
* registering HTML services.
|
||||
*
|
||||
* @param ContainerInterface $container The container
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function boot(ContainerInterface $container)
|
||||
{
|
||||
$finder = new Finder();
|
||||
$finder->setDatabase($container->get(DatabaseInterface::class));
|
||||
|
||||
$this->getRegistry()->register('finder', $finder);
|
||||
|
||||
$filter = new Filter();
|
||||
$filter->setDatabase($container->get(DatabaseInterface::class));
|
||||
|
||||
$this->getRegistry()->register('filter', $filter);
|
||||
|
||||
$this->getRegistry()->register('query', new Query());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Search Branches field for the Finder package.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class BranchesField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $type = 'Branches';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
Factory::getApplication()->bootComponent('com_finder');
|
||||
|
||||
return HTMLHelper::_('finder.mapslist');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\GroupedlistField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Supports a select grouped list of finder content map.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
class ContentmapField extends GroupedlistField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public $type = 'ContentMap';
|
||||
|
||||
/**
|
||||
* Method to get the list of content map options grouped by first level.
|
||||
*
|
||||
* @return array The field option objects as a nested array in groups.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
protected function getGroups()
|
||||
{
|
||||
$groups = [];
|
||||
|
||||
// Get the database object and a new query object.
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Main query.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('a.title', 'text'))
|
||||
->select($db->quoteName('a.id', 'value'))
|
||||
->select($db->quoteName('a.parent_id'))
|
||||
->select($db->quoteName('a.level'))
|
||||
->from($db->quoteName('#__finder_taxonomy', 'a'))
|
||||
->where($db->quoteName('a.parent_id') . ' <> 0')
|
||||
->order('a.title ASC');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$contentMap = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Build the grouped list array.
|
||||
if ($contentMap) {
|
||||
$parents = [];
|
||||
|
||||
foreach ($contentMap as $item) {
|
||||
if (!isset($parents[$item->parent_id])) {
|
||||
$parents[$item->parent_id] = [];
|
||||
}
|
||||
|
||||
$parents[$item->parent_id][] = $item;
|
||||
}
|
||||
|
||||
foreach ($parents[1] as $branch) {
|
||||
$text = Text::_(LanguageHelper::branchSingular($branch->text));
|
||||
$groups[$text] = $this->prepareLevel($branch->value, $parents);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge any additional groups in the XML definition.
|
||||
$groups = array_merge(parent::getGroups(), $groups);
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indenting and translating options for the list
|
||||
*
|
||||
* @param int $parent Parent ID to process
|
||||
* @param array $parents Array of arrays of items with parent IDs as keys
|
||||
*
|
||||
* @return array The indented list of entries for this branch
|
||||
*
|
||||
* @since 4.1.5
|
||||
*/
|
||||
private function prepareLevel($parent, $parents)
|
||||
{
|
||||
$lang = Factory::getLanguage();
|
||||
$entries = [];
|
||||
|
||||
foreach ($parents[$parent] as $item) {
|
||||
$levelPrefix = str_repeat('- ', $item->level - 1);
|
||||
|
||||
if (trim($item->text, '*') === 'Language') {
|
||||
$text = LanguageHelper::branchLanguageTitle($item->text);
|
||||
} else {
|
||||
$key = LanguageHelper::branchSingular($item->text);
|
||||
$text = $lang->hasKey($key) ? Text::_($key) : $item->text;
|
||||
}
|
||||
|
||||
$entries[] = HTMLHelper::_('select.option', $item->value, $levelPrefix . $text);
|
||||
|
||||
if (isset($parents[$item->value])) {
|
||||
$entries = array_merge($entries, $this->prepareLevel($item->value, $parents));
|
||||
}
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Content Types Filter field for the Finder package.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
class ContenttypesField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.6.0
|
||||
*/
|
||||
protected $type = 'ContentTypes';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$lang = Factory::getLanguage();
|
||||
$options = [];
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('id', 'value'))
|
||||
->select($db->quoteName('title', 'text'))
|
||||
->from($db->quoteName('#__finder_types'));
|
||||
|
||||
// Get the options.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$contentTypes = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
// Translate.
|
||||
foreach ($contentTypes as $contentType) {
|
||||
$key = LanguageHelper::branchSingular($contentType->text);
|
||||
$contentType->translatedText = $lang->hasKey($key) ? Text::_($key) : $contentType->text;
|
||||
}
|
||||
|
||||
// Order by title.
|
||||
$contentTypes = ArrayHelper::sortObjects($contentTypes, 'translatedText', 1, true, true);
|
||||
|
||||
// Convert the values to options.
|
||||
foreach ($contentTypes as $contentType) {
|
||||
$options[] = HTMLHelper::_('select.option', $contentType->value, $contentType->translatedText);
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
$options = array_merge(parent::getOptions(), $options);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Search Filter field for the Finder package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class SearchfilterField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $type = 'SearchFilter';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
// Build the query.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('f.title AS text, f.filter_id AS value')
|
||||
->from($db->quoteName('#__finder_filters') . ' AS f')
|
||||
->where('f.state = 1')
|
||||
->order('f.title ASC');
|
||||
$db->setQuery($query);
|
||||
$options = $db->loadObjectList();
|
||||
|
||||
array_unshift($options, HTMLHelper::_('select.option', '', Text::_('COM_FINDER_SELECT_SEARCH_FILTER'), 'value', 'text'));
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\CheckboxesField;
|
||||
|
||||
/**
|
||||
* Taxonomy Types field for the Finder package.
|
||||
* This is a helper to allow to save an empty set of
|
||||
* options by having a hidden field with a "none" value.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class TaxonomytypesField extends CheckboxesField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $type = 'TaxonomyTypes';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for a generic list.
|
||||
* Use the multiple attribute to enable multiselect.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$html = parent::getInput();
|
||||
|
||||
$data = $this->getLayoutData();
|
||||
$data['id'] .= '_hidden';
|
||||
$data['value'] = 'none';
|
||||
|
||||
return $html . $this->getRenderer('joomla.form.field.hidden')->render($data);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Extension\ExtensionHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Helper class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FinderHelper
|
||||
{
|
||||
/**
|
||||
* The extension name.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public static $extension = 'com_finder';
|
||||
|
||||
/**
|
||||
* Gets the finder system plugin extension id.
|
||||
*
|
||||
* @return integer The finder system plugin extension id.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public static function getFinderPluginId()
|
||||
{
|
||||
$pluginRecord = ExtensionHelper::getExtensionRecord('finder', 'plugin', null, 'content');
|
||||
|
||||
return $pluginRecord !== null ? $pluginRecord->extension_id : 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\LanguageHelper as CMSLanguageHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Finder language helper class.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class LanguageHelper
|
||||
{
|
||||
/**
|
||||
* Method to return a plural language code for a taxonomy branch.
|
||||
*
|
||||
* @param string $branchName Branch title.
|
||||
*
|
||||
* @return string Language key code.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function branchPlural($branchName)
|
||||
{
|
||||
$return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName));
|
||||
|
||||
if ($return !== '_') {
|
||||
return 'PLG_FINDER_QUERY_FILTER_BRANCH_P_' . $return;
|
||||
}
|
||||
|
||||
return $branchName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return a singular language code for a taxonomy branch.
|
||||
*
|
||||
* @param string $branchName Branch name.
|
||||
*
|
||||
* @return string Language key code.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function branchSingular($branchName)
|
||||
{
|
||||
$return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName));
|
||||
$language = Factory::getApplication()->getLanguage();
|
||||
|
||||
if ($language->hasKey('PLG_FINDER_QUERY_FILTER_BRANCH_S_' . $return) || JDEBUG) {
|
||||
return 'PLG_FINDER_QUERY_FILTER_BRANCH_S_' . $return;
|
||||
}
|
||||
|
||||
return $branchName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the language name for a language taxonomy branch.
|
||||
*
|
||||
* @param string $branchName Language branch name.
|
||||
*
|
||||
* @return string The language title.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public static function branchLanguageTitle($branchName)
|
||||
{
|
||||
$title = $branchName;
|
||||
|
||||
if ($branchName === '*') {
|
||||
$title = Text::_('JALL_LANGUAGE');
|
||||
} else {
|
||||
$languages = CMSLanguageHelper::getLanguages('lang_code');
|
||||
|
||||
if (isset($languages[$branchName])) {
|
||||
$title = $languages[$branchName]->title;
|
||||
}
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to load Smart Search component language file.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function loadComponentLanguage()
|
||||
{
|
||||
Factory::getLanguage()->load('com_finder', JPATH_SITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to load Smart Search plugin language files.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function loadPluginLanguage()
|
||||
{
|
||||
static $loaded = false;
|
||||
|
||||
// If already loaded, don't load again.
|
||||
if ($loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loaded = true;
|
||||
|
||||
// Get array of all the enabled Smart Search plugin names.
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select([$db->quoteName('name'), $db->quoteName('element')])
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
|
||||
->where($db->quoteName('folder') . ' = ' . $db->quote('finder'))
|
||||
->where($db->quoteName('enabled') . ' = 1');
|
||||
$db->setQuery($query);
|
||||
$plugins = $db->loadObjectList();
|
||||
|
||||
if (empty($plugins)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load generic language strings.
|
||||
$lang = Factory::getLanguage();
|
||||
$lang->load('plg_content_finder', JPATH_ADMINISTRATOR);
|
||||
|
||||
// Load language file for each plugin.
|
||||
foreach ($plugins as $plugin) {
|
||||
$lang->load($plugin->name, JPATH_ADMINISTRATOR)
|
||||
|| $lang->load($plugin->name, JPATH_PLUGINS . '/finder/' . $plugin->element);
|
||||
}
|
||||
}
|
||||
}
|
||||
942
administrator/components/com_finder/src/Indexer/Adapter.php
Normal file
942
administrator/components/com_finder/src/Indexer/Adapter.php
Normal file
@ -0,0 +1,942 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Database\QueryInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Prototype adapter class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
abstract class Adapter extends CMSPlugin
|
||||
{
|
||||
/**
|
||||
* The context is somewhat arbitrary but it must be unique or there will be
|
||||
* conflicts when managing plugin/indexer state. A good best practice is to
|
||||
* use the plugin name suffix as the context. For example, if the plugin is
|
||||
* named 'plgFinderContent', the context could be 'Content'.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The extension name.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The sublayout to use when rendering the results.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $layout;
|
||||
|
||||
/**
|
||||
* The mime type of the content the adapter indexes.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $mime;
|
||||
|
||||
/**
|
||||
* The access level of an item before save.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $old_access;
|
||||
|
||||
/**
|
||||
* The access level of a category before save.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $old_cataccess;
|
||||
|
||||
/**
|
||||
* The type of content the adapter indexes.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $type_title;
|
||||
|
||||
/**
|
||||
* The type id of the content.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $type_id;
|
||||
|
||||
/**
|
||||
* The database object.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* The table name.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The indexer object.
|
||||
*
|
||||
* @var Indexer
|
||||
* @since 3.0
|
||||
*/
|
||||
protected $indexer;
|
||||
|
||||
/**
|
||||
* The field the published state is stored in.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $state_field = 'state';
|
||||
|
||||
/**
|
||||
* Method to instantiate the indexer adapter.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher The object to observe.
|
||||
* @param array $config An array that holds the plugin configuration.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct(DispatcherInterface $dispatcher, array $config)
|
||||
{
|
||||
// Call the parent constructor.
|
||||
parent::__construct($dispatcher, $config);
|
||||
|
||||
// Get the type id.
|
||||
$this->type_id = $this->getTypeId();
|
||||
|
||||
// Add the content type if it doesn't exist and is set.
|
||||
if (empty($this->type_id) && !empty($this->type_title)) {
|
||||
$this->type_id = Helper::addContentType($this->type_title, $this->mime);
|
||||
}
|
||||
|
||||
// Check for a layout override.
|
||||
if ($this->params->get('layout')) {
|
||||
$this->layout = $this->params->get('layout');
|
||||
}
|
||||
|
||||
// Get the indexer object
|
||||
$this->indexer = new Indexer($this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onBeforeIndex' => 'onBeforeIndex',
|
||||
'onBuildIndex' => 'onBuildIndex',
|
||||
'onFinderGarbageCollection' => 'onFinderGarbageCollection',
|
||||
'onStartIndex' => 'onStartIndex',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the adapter state and push it into the indexer.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onStartIndex()
|
||||
{
|
||||
// Get the indexer state.
|
||||
$iState = Indexer::getState();
|
||||
|
||||
// Get the number of content items.
|
||||
$total = (int) $this->getContentCount();
|
||||
|
||||
// Add the content count to the total number of items.
|
||||
$iState->totalItems += $total;
|
||||
|
||||
// Populate the indexer state information for the adapter.
|
||||
$iState->pluginState[$this->context]['total'] = $total;
|
||||
$iState->pluginState[$this->context]['offset'] = 0;
|
||||
|
||||
// Set the indexer state.
|
||||
Indexer::setState($iState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to prepare for the indexer to be run. This method will often
|
||||
* be used to include dependencies and things of that nature.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onBeforeIndex()
|
||||
{
|
||||
// Get the indexer and adapter state.
|
||||
$iState = Indexer::getState();
|
||||
$aState = $iState->pluginState[$this->context];
|
||||
|
||||
// Check the progress of the indexer and the adapter.
|
||||
if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Run the setup method.
|
||||
return $this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to index a batch of content items. This method can be called by
|
||||
* the indexer many times throughout the indexing process depending on how
|
||||
* much content is available for indexing. It is important to track the
|
||||
* progress correctly so we can display it to the user.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onBuildIndex()
|
||||
{
|
||||
// Get the indexer and adapter state.
|
||||
$iState = Indexer::getState();
|
||||
$aState = $iState->pluginState[$this->context];
|
||||
|
||||
// Check the progress of the indexer and the adapter.
|
||||
if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the batch offset and size.
|
||||
$offset = (int) $aState['offset'];
|
||||
$limit = (int) ($iState->batchSize - $iState->batchOffset);
|
||||
|
||||
// Get the content items to index.
|
||||
$items = $this->getItems($offset, $limit);
|
||||
|
||||
// Iterate through the items and index them.
|
||||
for ($i = 0, $n = \count($items); $i < $n; $i++) {
|
||||
// Index the item.
|
||||
$this->index($items[$i]);
|
||||
|
||||
// Adjust the offsets.
|
||||
$offset++;
|
||||
$iState->batchOffset++;
|
||||
$iState->totalItems--;
|
||||
}
|
||||
|
||||
// Update the indexer state.
|
||||
$aState['offset'] = $offset;
|
||||
$iState->pluginState[$this->context] = $aState;
|
||||
Indexer::setState($iState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove outdated index entries
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function onFinderGarbageCollection()
|
||||
{
|
||||
$db = $this->db;
|
||||
$type_id = $this->getTypeId();
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
$subquery = $db->getQuery(true);
|
||||
$subquery->select('CONCAT(' . $db->quote($this->getUrl('', $this->extension, $this->layout)) . ', id)')
|
||||
->from($db->quoteName($this->table));
|
||||
$query->select($db->quoteName('l.link_id'))
|
||||
->from($db->quoteName('#__finder_links', 'l'))
|
||||
->where($db->quoteName('l.type_id') . ' = ' . $type_id)
|
||||
->where($db->quoteName('l.url') . ' LIKE ' . $db->quote($this->getUrl('%', $this->extension, $this->layout)))
|
||||
->where($db->quoteName('l.url') . ' NOT IN (' . $subquery . ')');
|
||||
$db->setQuery($query);
|
||||
$items = $db->loadColumn();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$this->indexer->remove($item);
|
||||
}
|
||||
|
||||
return \count($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the value of a content item's property in the links
|
||||
* table. This is used to synchronize published and access states that
|
||||
* are changed when not editing an item directly.
|
||||
*
|
||||
* @param string $id The ID of the item to change.
|
||||
* @param string $property The property that is being changed.
|
||||
* @param integer $value The new value of that property.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function change($id, $property, $value)
|
||||
{
|
||||
// Check for a property we know how to handle.
|
||||
if ($property !== 'state' && $property !== 'access') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the URL for the content id.
|
||||
$item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));
|
||||
|
||||
// Update the content items.
|
||||
$query = $this->db->getQuery(true)
|
||||
->update($this->db->quoteName('#__finder_links'))
|
||||
->set($this->db->quoteName($property) . ' = ' . (int) $value)
|
||||
->where($this->db->quoteName('url') . ' = ' . $item);
|
||||
$this->db->setQuery($query);
|
||||
$this->db->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to index an item.
|
||||
*
|
||||
* @param Result $item The item to index as a Result object.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
abstract protected function index(Result $item);
|
||||
|
||||
/**
|
||||
* Method to reindex an item.
|
||||
*
|
||||
* @param integer $id The ID of the item to reindex.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function reindex($id)
|
||||
{
|
||||
// Run the setup method.
|
||||
$this->setup();
|
||||
|
||||
// Get the item.
|
||||
$item = $this->getItem($id);
|
||||
|
||||
// Index the item.
|
||||
$this->index($item);
|
||||
|
||||
Taxonomy::removeOrphanNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove an item from the index.
|
||||
*
|
||||
* @param string $id The ID of the item to remove.
|
||||
* @param bool $removeTaxonomies Remove empty taxonomies
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function remove($id, $removeTaxonomies = true)
|
||||
{
|
||||
// Get the item's URL
|
||||
$url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));
|
||||
|
||||
// Get the link ids for the content items.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('link_id'))
|
||||
->from($this->db->quoteName('#__finder_links'))
|
||||
->where($this->db->quoteName('url') . ' = ' . $url);
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadColumn();
|
||||
|
||||
// Check the items.
|
||||
if (empty($items)) {
|
||||
Factory::getApplication()->triggerEvent('onFinderIndexAfterDelete', [$id]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove the items.
|
||||
foreach ($items as $item) {
|
||||
$this->indexer->remove($item, $removeTaxonomies);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to setup the adapter before indexing.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
abstract protected function setup();
|
||||
|
||||
/**
|
||||
* Method to update index data on category access level changes
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function categoryAccessChange($row)
|
||||
{
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('c.id = ' . (int) $row->id);
|
||||
|
||||
// Get the access level.
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadObjectList();
|
||||
|
||||
// Adjust the access level for each item within the category.
|
||||
foreach ($items as $item) {
|
||||
// Set the access level.
|
||||
$temp = max($item->access, $row->access);
|
||||
|
||||
// Update the item.
|
||||
$this->change((int) $item->id, 'access', $temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on category access level changes
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
* @param integer $value The value of the state that the content has been changed to.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function categoryStateChange($pks, $value)
|
||||
{
|
||||
/*
|
||||
* The item's published state is tied to the category
|
||||
* published state so we need to look up all published states
|
||||
* before we change anything.
|
||||
*/
|
||||
foreach ($pks as $pk) {
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('c.id = ' . (int) $pk);
|
||||
|
||||
// Get the published states.
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadObjectList();
|
||||
|
||||
// Adjust the state for each item within the category.
|
||||
foreach ($items as $item) {
|
||||
// Translate the state.
|
||||
$temp = $this->translateState($item->state, $value);
|
||||
|
||||
// Update the item.
|
||||
$this->change($item->id, 'state', $temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check the existing access level for categories
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function checkCategoryAccess($row)
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('access'))
|
||||
->from($this->db->quoteName('#__categories'))
|
||||
->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
// Store the access level to determine if it changes
|
||||
$this->old_cataccess = $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check the existing access level for items
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function checkItemAccess($row)
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('access'))
|
||||
->from($this->db->quoteName($this->table))
|
||||
->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
// Store the access level to determine if it changes
|
||||
$this->old_access = $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the number of content items available to index.
|
||||
*
|
||||
* @return integer The number of content items available to index.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getContentCount()
|
||||
{
|
||||
$return = 0;
|
||||
|
||||
// Get the list query.
|
||||
$query = $this->getListQuery();
|
||||
|
||||
// Check if the query is valid.
|
||||
if (empty($query)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Tweak the SQL query to make the total lookup faster.
|
||||
if ($query instanceof QueryInterface) {
|
||||
$query = clone $query;
|
||||
$query->clear('select')
|
||||
->select('COUNT(*)')
|
||||
->clear('order');
|
||||
}
|
||||
|
||||
// Get the total number of content items to index.
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return (int) $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a content item to index.
|
||||
*
|
||||
* @param integer $id The id of the content item.
|
||||
*
|
||||
* @return Result A Result object.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItem($id)
|
||||
{
|
||||
// Get the list query and add the extra WHERE clause.
|
||||
$query = $this->getListQuery();
|
||||
$query->where('a.id = ' . (int) $id);
|
||||
|
||||
// Get the item to index.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadAssoc();
|
||||
|
||||
// Convert the item to a result object.
|
||||
$item = ArrayHelper::toObject((array) $item, Result::class);
|
||||
|
||||
// Set the item type.
|
||||
$item->type_id = $this->type_id;
|
||||
|
||||
// Set the item layout.
|
||||
$item->layout = $this->layout;
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a list of content items to index.
|
||||
*
|
||||
* @param integer $offset The list offset.
|
||||
* @param integer $limit The list limit.
|
||||
* @param QueryInterface $query A QueryInterface object. [optional]
|
||||
*
|
||||
* @return Result[] An array of Result objects.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItems($offset, $limit, $query = null)
|
||||
{
|
||||
// Get the content items to index.
|
||||
$this->db->setQuery($this->getListQuery($query)->setLimit($limit, $offset));
|
||||
$items = $this->db->loadAssocList();
|
||||
|
||||
foreach ($items as &$item) {
|
||||
$item = ArrayHelper::toObject($item, Result::class);
|
||||
|
||||
// Set the item type.
|
||||
$item->type_id = $this->type_id;
|
||||
|
||||
// Set the mime type.
|
||||
$item->mime = $this->mime;
|
||||
|
||||
// Set the item layout.
|
||||
$item->layout = $this->layout;
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the SQL query used to retrieve the list of content items.
|
||||
*
|
||||
* @param mixed $query A QueryInterface object. [optional]
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getListQuery($query = null)
|
||||
{
|
||||
// Check if we can use the supplied SQL query.
|
||||
return $query instanceof QueryInterface ? $query : $this->db->getQuery(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the plugin type
|
||||
*
|
||||
* @param integer $id The plugin ID
|
||||
*
|
||||
* @return string|null The plugin type
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getPluginType($id)
|
||||
{
|
||||
// Prepare the query
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('element'))
|
||||
->from($this->db->quoteName('#__extensions'))
|
||||
->where($this->db->quoteName('folder') . ' = ' . $this->db->quote('finder'))
|
||||
->where($this->db->quoteName('extension_id') . ' = ' . (int) $id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a SQL query to load the published and access states for
|
||||
* an article and category.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getStateQuery()
|
||||
{
|
||||
$query = $this->db->getQuery(true);
|
||||
|
||||
// Item ID
|
||||
$query->select('a.id');
|
||||
|
||||
// Item and category published state
|
||||
$query->select('a.' . $this->state_field . ' AS state, c.published AS cat_state');
|
||||
|
||||
// Item and category access levels
|
||||
$query->select('a.access, c.access AS cat_access')
|
||||
->from($this->table . ' AS a')
|
||||
->join('LEFT', '#__categories AS c ON c.id = a.catid');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the query clause for getting items to update by time.
|
||||
*
|
||||
* @param string $time The modified timestamp.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getUpdateQueryByTime($time)
|
||||
{
|
||||
// Build an SQL query based on the modified time.
|
||||
$query = $this->db->getQuery(true)
|
||||
->where('a.modified >= ' . $this->db->quote($time));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the query clause for getting items to update by id.
|
||||
*
|
||||
* @param array $ids The ids to load.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getUpdateQueryByIds($ids)
|
||||
{
|
||||
// Build an SQL query based on the item ids.
|
||||
$query = $this->db->getQuery(true)
|
||||
->where('a.id IN(' . implode(',', $ids) . ')');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the type id for the adapter content.
|
||||
*
|
||||
* @return integer The numeric type id for the content.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getTypeId()
|
||||
{
|
||||
// Get the type id from the database.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('id'))
|
||||
->from($this->db->quoteName('#__finder_types'))
|
||||
->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title));
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return (int) $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the URL for the item. The URL is how we look up the link
|
||||
* in the Finder index.
|
||||
*
|
||||
* @param integer $id The id of the item.
|
||||
* @param string $extension The extension the category is in.
|
||||
* @param string $view The view for the URL.
|
||||
*
|
||||
* @return string The URL of the item.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getUrl($id, $extension, $view)
|
||||
{
|
||||
return 'index.php?option=' . $extension . '&view=' . $view . '&id=' . $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the page title of any menu item that is linked to the
|
||||
* content item, if it exists and is set.
|
||||
*
|
||||
* @param string $url The URL of the item.
|
||||
*
|
||||
* @return mixed The title on success, null if not found.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItemMenuTitle($url)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// Set variables
|
||||
$user = Factory::getUser();
|
||||
$groups = implode(',', $user->getAuthorisedViewLevels());
|
||||
|
||||
// Build a query to get the menu params.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('params'))
|
||||
->from($this->db->quoteName('#__menu'))
|
||||
->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url))
|
||||
->where($this->db->quoteName('published') . ' = 1')
|
||||
->where($this->db->quoteName('access') . ' IN (' . $groups . ')');
|
||||
|
||||
// Get the menu params from the database.
|
||||
$this->db->setQuery($query);
|
||||
$params = $this->db->loadResult();
|
||||
|
||||
// Check the results.
|
||||
if (empty($params)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Instantiate the params.
|
||||
$params = json_decode($params);
|
||||
|
||||
// Get the page title if it is set.
|
||||
if (isset($params->page_title) && $params->page_title) {
|
||||
$return = $params->page_title;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on access level changes
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function itemAccessChange($row)
|
||||
{
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('a.id = ' . (int) $row->id);
|
||||
|
||||
// Get the access level.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadObject();
|
||||
|
||||
// Set the access level.
|
||||
$temp = max($row->access, $item->cat_access);
|
||||
|
||||
// Update the item.
|
||||
$this->change((int) $row->id, 'access', $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on published state changes
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
* @param integer $value The value of the state that the content has been changed to.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function itemStateChange($pks, $value)
|
||||
{
|
||||
/*
|
||||
* The item's published state is tied to the category
|
||||
* published state so we need to look up all published states
|
||||
* before we change anything.
|
||||
*/
|
||||
foreach ($pks as $pk) {
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('a.id = ' . (int) $pk);
|
||||
|
||||
// Get the published states.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadObject();
|
||||
|
||||
// Translate the state.
|
||||
$temp = $this->translateState($value, $item->cat_state);
|
||||
|
||||
// Update the item.
|
||||
$this->change($pk, 'state', $temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data when a plugin is disabled
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function pluginDisable($pks)
|
||||
{
|
||||
// Since multiple plugins may be disabled at a time, we need to check first
|
||||
// that we're handling the appropriate one for the context
|
||||
foreach ($pks as $pk) {
|
||||
if ($this->getPluginType($pk) == strtolower($this->context)) {
|
||||
// Get all of the items to unindex them
|
||||
$query = clone $this->getStateQuery();
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadColumn();
|
||||
|
||||
// Remove each item
|
||||
foreach ($items as $item) {
|
||||
$this->remove($item);
|
||||
}
|
||||
// Stop processing plugins
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to translate the native content states into states that the
|
||||
* indexer can use.
|
||||
*
|
||||
* @param integer $item The item state.
|
||||
* @param integer $category The category state. [optional]
|
||||
*
|
||||
* @return integer The translated indexer state.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function translateState($item, $category = null)
|
||||
{
|
||||
// If category is present, factor in its states as well
|
||||
if ($category !== null && $category == 0) {
|
||||
$item = 0;
|
||||
}
|
||||
|
||||
// Translate the state
|
||||
switch ($item) {
|
||||
// Published items should always show up in search results
|
||||
case 1:
|
||||
return 1;
|
||||
|
||||
// Archived items should only show up when option is enabled
|
||||
case 2:
|
||||
if ($this->params->get('search_archived', 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
// All other states should return an unpublished state
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
969
administrator/components/com_finder/src/Indexer/DebugAdapter.php
Normal file
969
administrator/components/com_finder/src/Indexer/DebugAdapter.php
Normal file
@ -0,0 +1,969 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Database\QueryInterface;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
/**
|
||||
* Prototype debug adapter class for the Finder indexer package.
|
||||
* THIS CLASS IS ONLY TO BE USED FOR DEBUGGING PURPOSES! DON'T
|
||||
* USE IT FOR PRODUCTIVE USE!
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @internal
|
||||
*/
|
||||
abstract class DebugAdapter extends CMSPlugin
|
||||
{
|
||||
/**
|
||||
* The context is somewhat arbitrary but it must be unique or there will be
|
||||
* conflicts when managing plugin/indexer state. A good best practice is to
|
||||
* use the plugin name suffix as the context. For example, if the plugin is
|
||||
* named 'plgFinderContent', the context could be 'Content'.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
/**
|
||||
* The extension name.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The sublayout to use when rendering the results.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $layout;
|
||||
|
||||
/**
|
||||
* The mime type of the content the adapter indexes.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $mime;
|
||||
|
||||
/**
|
||||
* The access level of an item before save.
|
||||
*
|
||||
* @var integer
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $old_access;
|
||||
|
||||
/**
|
||||
* The access level of a category before save.
|
||||
*
|
||||
* @var integer
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $old_cataccess;
|
||||
|
||||
/**
|
||||
* The type of content the adapter indexes.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $type_title;
|
||||
|
||||
/**
|
||||
* The type id of the content.
|
||||
*
|
||||
* @var integer
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $type_id;
|
||||
|
||||
/**
|
||||
* The database object.
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* The table name.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The indexer object.
|
||||
*
|
||||
* @var Indexer
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $indexer;
|
||||
|
||||
/**
|
||||
* The field the published state is stored in.
|
||||
*
|
||||
* @var string
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $state_field = 'state';
|
||||
|
||||
/**
|
||||
* Method to instantiate the indexer adapter.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher The object to observe.
|
||||
* @param array $config An array that holds the plugin configuration.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function __construct(DispatcherInterface $dispatcher, array $config)
|
||||
{
|
||||
// Call the parent constructor.
|
||||
parent::__construct($dispatcher, $config);
|
||||
|
||||
// Get the type id.
|
||||
$this->type_id = $this->getTypeId();
|
||||
|
||||
// Add the content type if it doesn't exist and is set.
|
||||
if (empty($this->type_id) && !empty($this->type_title)) {
|
||||
$this->type_id = Helper::addContentType($this->type_title, $this->mime);
|
||||
}
|
||||
|
||||
// Check for a layout override.
|
||||
if ($this->params->get('layout')) {
|
||||
$this->layout = $this->params->get('layout');
|
||||
}
|
||||
|
||||
// Get the indexer object
|
||||
$this->indexer = new Indexer($this->db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
'onBeforeIndex' => 'onBeforeIndex',
|
||||
'onBuildIndex' => 'onBuildIndex',
|
||||
'onFinderGarbageCollection' => 'onFinderGarbageCollection',
|
||||
'onStartIndex' => 'onStartIndex',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the adapter state and push it into the indexer.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onStartIndex()
|
||||
{
|
||||
// Get the indexer state.
|
||||
$iState = Indexer::getState();
|
||||
|
||||
// Get the number of content items.
|
||||
$total = (int) $this->getContentCount();
|
||||
|
||||
// Add the content count to the total number of items.
|
||||
$iState->totalItems += $total;
|
||||
|
||||
// Populate the indexer state information for the adapter.
|
||||
$iState->pluginState[$this->context]['total'] = $total;
|
||||
$iState->pluginState[$this->context]['offset'] = 0;
|
||||
|
||||
// Set the indexer state.
|
||||
Indexer::setState($iState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to prepare for the indexer to be run. This method will often
|
||||
* be used to include dependencies and things of that nature.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onBeforeIndex()
|
||||
{
|
||||
// Get the indexer and adapter state.
|
||||
$iState = Indexer::getState();
|
||||
$aState = $iState->pluginState[$this->context];
|
||||
|
||||
// Check the progress of the indexer and the adapter.
|
||||
if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Run the setup method.
|
||||
return $this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to index a batch of content items. This method can be called by
|
||||
* the indexer many times throughout the indexing process depending on how
|
||||
* much content is available for indexing. It is important to track the
|
||||
* progress correctly so we can display it to the user.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on error.
|
||||
*/
|
||||
public function onBuildIndex()
|
||||
{
|
||||
// Get the indexer and adapter state.
|
||||
$iState = Indexer::getState();
|
||||
$aState = $iState->pluginState[$this->context];
|
||||
|
||||
// Check the progress of the indexer and the adapter.
|
||||
if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the batch offset and size.
|
||||
$offset = (int) $aState['offset'];
|
||||
$limit = (int) ($iState->batchSize - $iState->batchOffset);
|
||||
|
||||
// Get the content items to index.
|
||||
$items = $this->getItems($offset, $limit);
|
||||
|
||||
// Iterate through the items and index them.
|
||||
for ($i = 0, $n = \count($items); $i < $n; $i++) {
|
||||
// Index the item.
|
||||
$this->index($items[$i]);
|
||||
|
||||
// Adjust the offsets.
|
||||
$offset++;
|
||||
$iState->batchOffset++;
|
||||
$iState->totalItems--;
|
||||
}
|
||||
|
||||
// Update the indexer state.
|
||||
$aState['offset'] = $offset;
|
||||
$iState->pluginState[$this->context] = $aState;
|
||||
Indexer::setState($iState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove outdated index entries
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function onFinderGarbageCollection()
|
||||
{
|
||||
$db = $this->db;
|
||||
$type_id = $this->getTypeId();
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
$subquery = $db->getQuery(true);
|
||||
$subquery->select('CONCAT(' . $db->quote($this->getUrl('', $this->extension, $this->layout)) . ', id)')
|
||||
->from($db->quoteName($this->table));
|
||||
$query->select($db->quoteName('l.link_id'))
|
||||
->from($db->quoteName('#__finder_links', 'l'))
|
||||
->where($db->quoteName('l.type_id') . ' = ' . $type_id)
|
||||
->where($db->quoteName('l.url') . ' LIKE ' . $db->quote($this->getUrl('%', $this->extension, $this->layout)))
|
||||
->where($db->quoteName('l.url') . ' NOT IN (' . $subquery . ')');
|
||||
$db->setQuery($query);
|
||||
$items = $db->loadColumn();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$this->indexer->remove($item);
|
||||
}
|
||||
|
||||
return \count($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the value of a content item's property in the links
|
||||
* table. This is used to synchronize published and access states that
|
||||
* are changed when not editing an item directly.
|
||||
*
|
||||
* @param string $id The ID of the item to change.
|
||||
* @param string $property The property that is being changed.
|
||||
* @param integer $value The new value of that property.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function change($id, $property, $value)
|
||||
{
|
||||
// Check for a property we know how to handle.
|
||||
if ($property !== 'state' && $property !== 'access') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the URL for the content id.
|
||||
$item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));
|
||||
|
||||
// Update the content items.
|
||||
$query = $this->db->getQuery(true)
|
||||
->update($this->db->quoteName('#__finder_links'))
|
||||
->set($this->db->quoteName($property) . ' = ' . (int) $value)
|
||||
->where($this->db->quoteName('url') . ' = ' . $item);
|
||||
$this->db->setQuery($query);
|
||||
$this->db->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to index an item.
|
||||
*
|
||||
* @param Result $item The item to index as a Result object.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
abstract protected function index(Result $item);
|
||||
|
||||
/**
|
||||
* Method to reindex an item.
|
||||
*
|
||||
* @param integer $id The ID of the item to reindex.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function reindex($id)
|
||||
{
|
||||
// Run the setup method.
|
||||
$this->setup();
|
||||
|
||||
// Remove the old item.
|
||||
$this->remove($id, false);
|
||||
|
||||
// Get the item.
|
||||
$item = $this->getItem($id);
|
||||
|
||||
// Index the item.
|
||||
$this->index($item);
|
||||
|
||||
Taxonomy::removeOrphanNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove an item from the index.
|
||||
*
|
||||
* @param string $id The ID of the item to remove.
|
||||
* @param bool $removeTaxonomies Remove empty taxonomies
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function remove($id, $removeTaxonomies = true)
|
||||
{
|
||||
// Get the item's URL
|
||||
$url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout));
|
||||
|
||||
// Get the link ids for the content items.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('link_id'))
|
||||
->from($this->db->quoteName('#__finder_links'))
|
||||
->where($this->db->quoteName('url') . ' = ' . $url);
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadColumn();
|
||||
|
||||
// Check the items.
|
||||
if (empty($items)) {
|
||||
$this->getApplication()->triggerEvent('onFinderIndexAfterDelete', [$id]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove the items.
|
||||
foreach ($items as $item) {
|
||||
$this->indexer->remove($item, $removeTaxonomies);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to setup the adapter before indexing.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
abstract protected function setup();
|
||||
|
||||
/**
|
||||
* Method to update index data on category access level changes
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function categoryAccessChange($row)
|
||||
{
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('c.id = ' . (int) $row->id);
|
||||
|
||||
// Get the access level.
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadObjectList();
|
||||
|
||||
// Adjust the access level for each item within the category.
|
||||
foreach ($items as $item) {
|
||||
// Set the access level.
|
||||
$temp = max($item->access, $row->access);
|
||||
|
||||
// Update the item.
|
||||
$this->change((int) $item->id, 'access', $temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on category access level changes
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
* @param integer $value The value of the state that the content has been changed to.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function categoryStateChange($pks, $value)
|
||||
{
|
||||
/*
|
||||
* The item's published state is tied to the category
|
||||
* published state so we need to look up all published states
|
||||
* before we change anything.
|
||||
*/
|
||||
foreach ($pks as $pk) {
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('c.id = ' . (int) $pk);
|
||||
|
||||
// Get the published states.
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadObjectList();
|
||||
|
||||
// Adjust the state for each item within the category.
|
||||
foreach ($items as $item) {
|
||||
// Translate the state.
|
||||
$temp = $this->translateState($item->state, $value);
|
||||
|
||||
// Update the item.
|
||||
$this->change($item->id, 'state', $temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check the existing access level for categories
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function checkCategoryAccess($row)
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('access'))
|
||||
->from($this->db->quoteName('#__categories'))
|
||||
->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
// Store the access level to determine if it changes
|
||||
$this->old_cataccess = $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check the existing access level for items
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function checkItemAccess($row)
|
||||
{
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('access'))
|
||||
->from($this->db->quoteName($this->table))
|
||||
->where($this->db->quoteName('id') . ' = ' . (int) $row->id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
// Store the access level to determine if it changes
|
||||
$this->old_access = $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the number of content items available to index.
|
||||
*
|
||||
* @return integer The number of content items available to index.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getContentCount()
|
||||
{
|
||||
$return = 0;
|
||||
|
||||
// Get the list query.
|
||||
$query = $this->getListQuery();
|
||||
|
||||
// Check if the query is valid.
|
||||
if (empty($query)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Tweak the SQL query to make the total lookup faster.
|
||||
if ($query instanceof QueryInterface) {
|
||||
$query = clone $query;
|
||||
$query->clear('select')
|
||||
->select('COUNT(*)')
|
||||
->clear('order');
|
||||
}
|
||||
|
||||
// Get the total number of content items to index.
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return (int) $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a content item to index.
|
||||
*
|
||||
* @param integer $id The id of the content item.
|
||||
*
|
||||
* @return Result A Result object.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItem($id)
|
||||
{
|
||||
// Get the list query and add the extra WHERE clause.
|
||||
$query = $this->getListQuery();
|
||||
$query->where('a.id = ' . (int) $id);
|
||||
|
||||
// Get the item to index.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadAssoc();
|
||||
|
||||
// Convert the item to a result object.
|
||||
$item = ArrayHelper::toObject((array) $item, Result::class);
|
||||
|
||||
// Set the item type.
|
||||
$item->type_id = $this->type_id;
|
||||
|
||||
// Set the item layout.
|
||||
$item->layout = $this->layout;
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a list of content items to index.
|
||||
*
|
||||
* @param integer $offset The list offset.
|
||||
* @param integer $limit The list limit.
|
||||
* @param QueryInterface $query A QueryInterface object. [optional]
|
||||
*
|
||||
* @return Result[] An array of Result objects.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItems($offset, $limit, $query = null)
|
||||
{
|
||||
// Get the content items to index.
|
||||
$this->db->setQuery($this->getListQuery($query)->setLimit($limit, $offset));
|
||||
$items = $this->db->loadAssocList();
|
||||
|
||||
foreach ($items as &$item) {
|
||||
$item = ArrayHelper::toObject($item, Result::class);
|
||||
|
||||
// Set the item type.
|
||||
$item->type_id = $this->type_id;
|
||||
|
||||
// Set the mime type.
|
||||
$item->mime = $this->mime;
|
||||
|
||||
// Set the item layout.
|
||||
$item->layout = $this->layout;
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the SQL query used to retrieve the list of content items.
|
||||
*
|
||||
* @param mixed $query A QueryInterface object. [optional]
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getListQuery($query = null)
|
||||
{
|
||||
// Check if we can use the supplied SQL query.
|
||||
return $query instanceof QueryInterface ? $query : $this->db->getQuery(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the plugin type
|
||||
*
|
||||
* @param integer $id The plugin ID
|
||||
*
|
||||
* @return string The plugin type
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getPluginType($id)
|
||||
{
|
||||
// Prepare the query
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('element'))
|
||||
->from($this->db->quoteName('#__extensions'))
|
||||
->where($this->db->quoteName('extension_id') . ' = ' . (int) $id);
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a SQL query to load the published and access states for
|
||||
* an article and category.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getStateQuery()
|
||||
{
|
||||
$query = $this->db->getQuery(true);
|
||||
|
||||
// Item ID
|
||||
$query->select('a.id');
|
||||
|
||||
// Item and category published state
|
||||
$query->select('a.' . $this->state_field . ' AS state, c.published AS cat_state');
|
||||
|
||||
// Item and category access levels
|
||||
$query->select('a.access, c.access AS cat_access')
|
||||
->from($this->table . ' AS a')
|
||||
->join('LEFT', '#__categories AS c ON c.id = a.catid');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the query clause for getting items to update by time.
|
||||
*
|
||||
* @param string $time The modified timestamp.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getUpdateQueryByTime($time)
|
||||
{
|
||||
// Build an SQL query based on the modified time.
|
||||
$query = $this->db->getQuery(true)
|
||||
->where('a.modified >= ' . $this->db->quote($time));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the query clause for getting items to update by id.
|
||||
*
|
||||
* @param array $ids The ids to load.
|
||||
*
|
||||
* @return QueryInterface A database object.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getUpdateQueryByIds($ids)
|
||||
{
|
||||
// Build an SQL query based on the item ids.
|
||||
$query = $this->db->getQuery(true)
|
||||
->where('a.id IN(' . implode(',', $ids) . ')');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the type id for the adapter content.
|
||||
*
|
||||
* @return integer The numeric type id for the content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getTypeId()
|
||||
{
|
||||
// Get the type id from the database.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('id'))
|
||||
->from($this->db->quoteName('#__finder_types'))
|
||||
->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title));
|
||||
$this->db->setQuery($query);
|
||||
|
||||
return (int) $this->db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the URL for the item. The URL is how we look up the link
|
||||
* in the Finder index.
|
||||
*
|
||||
* @param integer $id The id of the item.
|
||||
* @param string $extension The extension the category is in.
|
||||
* @param string $view The view for the URL.
|
||||
*
|
||||
* @return string The URL of the item.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function getUrl($id, $extension, $view)
|
||||
{
|
||||
return 'index.php?option=' . $extension . '&view=' . $view . '&id=' . $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the page title of any menu item that is linked to the
|
||||
* content item, if it exists and is set.
|
||||
*
|
||||
* @param string $url The URL of the item.
|
||||
*
|
||||
* @return mixed The title on success, null if not found.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
protected function getItemMenuTitle($url)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// Set variables
|
||||
$user = $this->getApplication()->getIdentity();
|
||||
$groups = implode(',', $user->getAuthorisedViewLevels());
|
||||
|
||||
// Build a query to get the menu params.
|
||||
$query = $this->db->getQuery(true)
|
||||
->select($this->db->quoteName('params'))
|
||||
->from($this->db->quoteName('#__menu'))
|
||||
->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url))
|
||||
->where($this->db->quoteName('published') . ' = 1')
|
||||
->where($this->db->quoteName('access') . ' IN (' . $groups . ')');
|
||||
|
||||
// Get the menu params from the database.
|
||||
$this->db->setQuery($query);
|
||||
$params = $this->db->loadResult();
|
||||
|
||||
// Check the results.
|
||||
if (empty($params)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Instantiate the params.
|
||||
$params = json_decode($params);
|
||||
|
||||
// Get the page title if it is set.
|
||||
if (isset($params->page_title) && $params->page_title) {
|
||||
$return = $params->page_title;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on access level changes
|
||||
*
|
||||
* @param Table $row A Table object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function itemAccessChange($row)
|
||||
{
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('a.id = ' . (int) $row->id);
|
||||
|
||||
// Get the access level.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadObject();
|
||||
|
||||
// Set the access level.
|
||||
$temp = max($row->access, $item->cat_access);
|
||||
|
||||
// Update the item.
|
||||
$this->change((int) $row->id, 'access', $temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data on published state changes
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
* @param integer $value The value of the state that the content has been changed to.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function itemStateChange($pks, $value)
|
||||
{
|
||||
/*
|
||||
* The item's published state is tied to the category
|
||||
* published state so we need to look up all published states
|
||||
* before we change anything.
|
||||
*/
|
||||
foreach ($pks as $pk) {
|
||||
$query = clone $this->getStateQuery();
|
||||
$query->where('a.id = ' . (int) $pk);
|
||||
|
||||
// Get the published states.
|
||||
$this->db->setQuery($query);
|
||||
$item = $this->db->loadObject();
|
||||
|
||||
// Translate the state.
|
||||
$temp = $this->translateState($value, $item->cat_state);
|
||||
|
||||
// Update the item.
|
||||
$this->change($pk, 'state', $temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update index data when a plugin is disabled
|
||||
*
|
||||
* @param array $pks A list of primary key ids of the content that has changed state.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function pluginDisable($pks)
|
||||
{
|
||||
// Since multiple plugins may be disabled at a time, we need to check first
|
||||
// that we're handling the appropriate one for the context
|
||||
foreach ($pks as $pk) {
|
||||
if ($this->getPluginType($pk) == strtolower($this->context)) {
|
||||
// Get all of the items to unindex them
|
||||
$query = clone $this->getStateQuery();
|
||||
$this->db->setQuery($query);
|
||||
$items = $this->db->loadColumn();
|
||||
|
||||
// Remove each item
|
||||
foreach ($items as $item) {
|
||||
$this->remove($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to translate the native content states into states that the
|
||||
* indexer can use.
|
||||
*
|
||||
* @param integer $item The item state.
|
||||
* @param integer $category The category state. [optional]
|
||||
*
|
||||
* @return integer The translated indexer state.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function translateState($item, $category = null)
|
||||
{
|
||||
// If category is present, factor in its states as well
|
||||
if ($category !== null && $category == 0) {
|
||||
$item = 0;
|
||||
}
|
||||
|
||||
// Translate the state
|
||||
switch ($item) {
|
||||
// Published and archived items only should return a published state
|
||||
case 1:
|
||||
case 2:
|
||||
return 1;
|
||||
|
||||
// All other states should return an unpublished state
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug method to set the used indexer
|
||||
*
|
||||
* @param Indexer $indexer Indexer object
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function setIndexer(Indexer $indexer)
|
||||
{
|
||||
$this->indexer = $indexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug method to run a specific plugin to prepare a result object.
|
||||
* The object is then stored in the indexer object to debug further.
|
||||
*
|
||||
* @param mixed $id ID to index
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function debug($id)
|
||||
{
|
||||
// Run the setup method.
|
||||
$this->setup();
|
||||
|
||||
// Get the item.
|
||||
$item = $this->getItem($id);
|
||||
|
||||
// Index the item.
|
||||
$this->index($item);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
/**
|
||||
* Debugging indexer class for the Finder indexer package.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @internal
|
||||
*/
|
||||
class DebugIndexer extends Indexer
|
||||
{
|
||||
/**
|
||||
* The result object from the last call to self::index()
|
||||
*
|
||||
* @var Result
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static $item;
|
||||
|
||||
/**
|
||||
* Stub for index() in indexer class
|
||||
*
|
||||
* @param Result $item Result object to index
|
||||
* @param string $format Format to index
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function index($item, $format = 'html')
|
||||
{
|
||||
self::$item = $item;
|
||||
}
|
||||
}
|
||||
484
administrator/components/com_finder/src/Indexer/Helper.php
Normal file
484
administrator/components/com_finder/src/Indexer/Helper.php
Normal file
@ -0,0 +1,484 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Event\Finder\PrepareContentEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Component\Fields\Administrator\Helper\FieldsHelper;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Helper class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
public const CUSTOMFIELDS_DONT_INDEX = 0;
|
||||
public const CUSTOMFIELDS_ADD_TO_INDEX = 1;
|
||||
public const CUSTOMFIELDS_ADD_TO_TAXONOMY = 2;
|
||||
public const CUSTOMFIELDS_ADD_TO_BOTH = 3;
|
||||
|
||||
/**
|
||||
* Method to parse input into plain text.
|
||||
*
|
||||
* @param string $input The raw input.
|
||||
* @param string $format The format of the input. [optional]
|
||||
*
|
||||
* @return string The parsed input.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on invalid parser.
|
||||
*/
|
||||
public static function parse($input, $format = 'html')
|
||||
{
|
||||
// Get a parser for the specified format and parse the input.
|
||||
return Parser::getInstance($format)->parse($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to tokenize a text string.
|
||||
*
|
||||
* @param string $input The input to tokenize.
|
||||
* @param string $lang The language of the input.
|
||||
* @param boolean $phrase Flag to indicate whether input could be a phrase. [optional]
|
||||
*
|
||||
* @return Token[] An array of Token objects.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function tokenize($input, $lang, $phrase = false)
|
||||
{
|
||||
static $cache = [], $tuplecount;
|
||||
static $multilingual;
|
||||
static $defaultLanguage;
|
||||
|
||||
if (!$tuplecount) {
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$tuplecount = $params->get('tuplecount', 1);
|
||||
}
|
||||
|
||||
if (\is_null($multilingual)) {
|
||||
$multilingual = Multilanguage::isEnabled();
|
||||
$config = ComponentHelper::getParams('com_finder');
|
||||
|
||||
if ($config->get('language_default', '') == '') {
|
||||
$defaultLang = '*';
|
||||
} elseif ($config->get('language_default', '') == '-1') {
|
||||
$defaultLang = self::getDefaultLanguage();
|
||||
} else {
|
||||
$defaultLang = $config->get('language_default');
|
||||
}
|
||||
|
||||
/*
|
||||
* The default language always has the language code '*'.
|
||||
* In order to not overwrite the language code of the language
|
||||
* object that we are using, we are cloning it here.
|
||||
*/
|
||||
$obj = Language::getInstance($defaultLang);
|
||||
$defaultLanguage = clone $obj;
|
||||
$defaultLanguage->language = '*';
|
||||
}
|
||||
|
||||
if (!$multilingual || $lang == '*') {
|
||||
$language = $defaultLanguage;
|
||||
} else {
|
||||
$language = Language::getInstance($lang);
|
||||
}
|
||||
|
||||
if (!isset($cache[$lang])) {
|
||||
$cache[$lang] = [];
|
||||
}
|
||||
|
||||
$tokens = [];
|
||||
$terms = $language->tokenise($input);
|
||||
|
||||
// @todo: array_filter removes any number 0's from the terms. Not sure this is entirely intended
|
||||
$terms = array_filter($terms);
|
||||
$terms = array_values($terms);
|
||||
|
||||
/*
|
||||
* If we have to handle the input as a phrase, that means we don't
|
||||
* tokenize the individual terms and we do not create the two and three
|
||||
* term combinations. The phrase must contain more than one word!
|
||||
*/
|
||||
if ($phrase === true && \count($terms) > 1) {
|
||||
// Create tokens from the phrase.
|
||||
$tokens[] = new Token($terms, $language->language, $language->spacer);
|
||||
} else {
|
||||
// Create tokens from the terms.
|
||||
for ($i = 0, $n = \count($terms); $i < $n; $i++) {
|
||||
if (isset($cache[$lang][$terms[$i]])) {
|
||||
$tokens[] = $cache[$lang][$terms[$i]];
|
||||
} else {
|
||||
$token = new Token($terms[$i], $language->language);
|
||||
$tokens[] = $token;
|
||||
$cache[$lang][$terms[$i]] = $token;
|
||||
}
|
||||
}
|
||||
|
||||
// Create multi-word phrase tokens from the individual words.
|
||||
if ($tuplecount > 1) {
|
||||
for ($i = 0, $n = \count($tokens); $i < $n; $i++) {
|
||||
$temp = [$tokens[$i]->term];
|
||||
|
||||
// Create tokens for 2 to $tuplecount length phrases
|
||||
for ($j = 1; $j < $tuplecount; $j++) {
|
||||
if ($i + $j >= $n || !isset($tokens[$i + $j])) {
|
||||
break;
|
||||
}
|
||||
|
||||
$temp[] = $tokens[$i + $j]->term;
|
||||
$key = implode('::', $temp);
|
||||
|
||||
if (isset($cache[$lang][$key])) {
|
||||
$tokens[] = $cache[$lang][$key];
|
||||
} else {
|
||||
$token = new Token($temp, $language->language, $language->spacer);
|
||||
$token->derived = true;
|
||||
$tokens[] = $token;
|
||||
$cache[$lang][$key] = $token;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent the cache to fill up the memory
|
||||
while (\count($cache[$lang]) > 1024) {
|
||||
/**
|
||||
* We want to cache the most common words/tokens. At the same time
|
||||
* we don't want to cache too much. The most common words will also
|
||||
* be early in the text, so we are dropping all terms/tokens which
|
||||
* have been cached later.
|
||||
*/
|
||||
array_pop($cache[$lang]);
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the base word of a token.
|
||||
*
|
||||
* @param string $token The token to stem.
|
||||
* @param string $lang The language of the token.
|
||||
*
|
||||
* @return string The root token.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function stem($token, $lang)
|
||||
{
|
||||
static $multilingual;
|
||||
static $defaultStemmer;
|
||||
|
||||
if (\is_null($multilingual)) {
|
||||
$multilingual = Multilanguage::isEnabled();
|
||||
$config = ComponentHelper::getParams('com_finder');
|
||||
|
||||
if ($config->get('language_default', '') == '') {
|
||||
$defaultStemmer = Language::getInstance('*');
|
||||
} elseif ($config->get('language_default', '') == '-1') {
|
||||
$defaultStemmer = Language::getInstance(self::getDefaultLanguage());
|
||||
} else {
|
||||
$defaultStemmer = Language::getInstance($config->get('language_default'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$multilingual || $lang == '*') {
|
||||
$language = $defaultStemmer;
|
||||
} else {
|
||||
$language = Language::getInstance($lang);
|
||||
}
|
||||
|
||||
return $language->stem($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a content type to the database.
|
||||
*
|
||||
* @param string $title The type of content. For example: PDF
|
||||
* @param string $mime The mime type of the content. For example: PDF [optional]
|
||||
*
|
||||
* @return integer The id of the content type.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
public static function addContentType($title, $mime = null)
|
||||
{
|
||||
static $types;
|
||||
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// Check if the types are loaded.
|
||||
if (empty($types)) {
|
||||
// Build the query to get the types.
|
||||
$query->select('*')
|
||||
->from($db->quoteName('#__finder_types'));
|
||||
|
||||
// Get the types.
|
||||
$db->setQuery($query);
|
||||
$types = $db->loadObjectList('title');
|
||||
}
|
||||
|
||||
// Check if the type already exists.
|
||||
if (isset($types[$title])) {
|
||||
return (int) $types[$title]->id;
|
||||
}
|
||||
|
||||
// Add the type.
|
||||
$query->clear()
|
||||
->insert($db->quoteName('#__finder_types'))
|
||||
->columns([$db->quoteName('title'), $db->quoteName('mime')])
|
||||
->values($db->quote($title) . ', ' . $db->quote($mime));
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
// Return the new id.
|
||||
return (int) $db->insertid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if a token is common in a language.
|
||||
*
|
||||
* @param string $token The token to test.
|
||||
* @param string $lang The language to reference.
|
||||
*
|
||||
* @return boolean True if common, false otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function isCommon($token, $lang)
|
||||
{
|
||||
static $data = [], $default, $multilingual;
|
||||
|
||||
if (\is_null($multilingual)) {
|
||||
$multilingual = Multilanguage::isEnabled();
|
||||
$config = ComponentHelper::getParams('com_finder');
|
||||
|
||||
if ($config->get('language_default', '') == '') {
|
||||
$default = '*';
|
||||
} elseif ($config->get('language_default', '') == '-1') {
|
||||
$default = self::getPrimaryLanguage(self::getDefaultLanguage());
|
||||
} else {
|
||||
$default = self::getPrimaryLanguage($config->get('language_default'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$multilingual || $lang == '*') {
|
||||
$lang = $default;
|
||||
}
|
||||
|
||||
// Load the common tokens for the language if necessary.
|
||||
if (!isset($data[$lang])) {
|
||||
$data[$lang] = self::getCommonWords($lang);
|
||||
}
|
||||
|
||||
// Check if the token is in the common array.
|
||||
return \in_array($token, $data[$lang], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of common terms for a language.
|
||||
*
|
||||
* @param string $lang The language to use.
|
||||
*
|
||||
* @return array Array of common terms.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
public static function getCommonWords($lang)
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Create the query to load all the common terms for the language.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('term'))
|
||||
->from($db->quoteName('#__finder_terms_common'))
|
||||
->where($db->quoteName('language') . ' = ' . $db->quote($lang));
|
||||
|
||||
// Load all of the common terms for the language.
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the default language for the site.
|
||||
*
|
||||
* @return string The default language string.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function getDefaultLanguage()
|
||||
{
|
||||
static $lang;
|
||||
|
||||
// We need to go to com_languages to get the site default language, it's the best we can guess.
|
||||
if (empty($lang)) {
|
||||
$lang = ComponentHelper::getParams('com_languages')->get('site', 'en-GB');
|
||||
}
|
||||
|
||||
return $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to parse a language/locale key and return a simple language string.
|
||||
*
|
||||
* @param string $lang The language/locale key. For example: en-GB
|
||||
*
|
||||
* @return string The simple language string. For example: en
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function getPrimaryLanguage($lang)
|
||||
{
|
||||
static $data = [];
|
||||
|
||||
// Only parse the identifier if necessary.
|
||||
if (!isset($data[$lang])) {
|
||||
if (\is_callable(['Locale', 'getPrimaryLanguage'])) {
|
||||
// Get the language key using the Locale package.
|
||||
$data[$lang] = \Locale::getPrimaryLanguage($lang);
|
||||
} else {
|
||||
// Get the language key using string position.
|
||||
$data[$lang] = StringHelper::substr($lang, 0, StringHelper::strpos($lang, '-'));
|
||||
}
|
||||
}
|
||||
|
||||
return $data[$lang];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get extra data for a content before being indexed. This is how
|
||||
* we add Comments, Tags, Labels, etc. that should be available to Finder.
|
||||
*
|
||||
* @param Result $item The item to index as a Result object.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error.
|
||||
*/
|
||||
public static function getContentExtras(Result $item)
|
||||
{
|
||||
$dispatcher = Factory::getApplication()->getDispatcher();
|
||||
|
||||
// Load the finder plugin group.
|
||||
PluginHelper::importPlugin('finder', null, true, $dispatcher);
|
||||
|
||||
$dispatcher->dispatch('onPrepareFinderContent', new PrepareContentEvent('onPrepareFinderContent', [
|
||||
'subject' => $item,
|
||||
]));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom fields for the item to the Result object
|
||||
*
|
||||
* @param Result $item Result object to add the custom fields to
|
||||
* @param string $context Context of the item in the custom fields
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function addCustomFields(Result $item, $context)
|
||||
{
|
||||
if (!ComponentHelper::getParams(strstr($context, '.', true))->get('custom_fields_enable', 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$obj = new \stdClass();
|
||||
$obj->id = $item->id;
|
||||
|
||||
$fields = FieldsHelper::getFields($context, $obj, true);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$searchindex = $field->params->get('searchindex', 0);
|
||||
|
||||
// We want to add this field to the search index
|
||||
if ($searchindex == self::CUSTOMFIELDS_ADD_TO_INDEX || $searchindex == self::CUSTOMFIELDS_ADD_TO_BOTH) {
|
||||
$name = 'jsfield_' . $field->name;
|
||||
$item->$name = $field->value;
|
||||
$item->addInstruction(Indexer::META_CONTEXT, $name);
|
||||
}
|
||||
|
||||
// We want to add this field as a taxonomy
|
||||
if (
|
||||
($searchindex == self::CUSTOMFIELDS_ADD_TO_TAXONOMY || $searchindex == self::CUSTOMFIELDS_ADD_TO_BOTH)
|
||||
&& $field->value
|
||||
) {
|
||||
$item->addTaxonomy($field->title, $field->value, $field->state, $field->access, $field->language);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to process content text using the onContentPrepare event trigger.
|
||||
*
|
||||
* @param string $text The content to process.
|
||||
* @param Registry $params The parameters object. [optional]
|
||||
* @param ?Result $item The item which get prepared. [optional]
|
||||
*
|
||||
* @return string The processed content.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function prepareContent($text, $params = null, Result $item = null)
|
||||
{
|
||||
static $loaded;
|
||||
|
||||
// Load the content plugins if necessary.
|
||||
if (empty($loaded)) {
|
||||
PluginHelper::importPlugin('content');
|
||||
$loaded = true;
|
||||
}
|
||||
|
||||
// Instantiate the parameter object if necessary.
|
||||
if (!($params instanceof Registry)) {
|
||||
$registry = new Registry($params);
|
||||
$params = $registry;
|
||||
}
|
||||
|
||||
// Create a mock content object.
|
||||
$content = Table::getInstance('Content');
|
||||
$content->text = $text;
|
||||
|
||||
if ($item) {
|
||||
$content->bind((array) $item);
|
||||
$content->bind($item->getElements());
|
||||
}
|
||||
|
||||
if ($item && !empty($item->context)) {
|
||||
$content->context = $item->context;
|
||||
}
|
||||
|
||||
// Fire the onContentPrepare event.
|
||||
Factory::getApplication()->triggerEvent('onContentPrepare', ['com_finder.indexer', &$content, &$params, 0]);
|
||||
|
||||
return $content->text;
|
||||
}
|
||||
}
|
||||
1023
administrator/components/com_finder/src/Indexer/Indexer.php
Normal file
1023
administrator/components/com_finder/src/Indexer/Indexer.php
Normal file
File diff suppressed because it is too large
Load Diff
182
administrator/components/com_finder/src/Indexer/Language.php
Normal file
182
administrator/components/com_finder/src/Indexer/Language.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\String\StringHelper;
|
||||
use Wamania\Snowball\NotFoundException;
|
||||
use Wamania\Snowball\Stemmer\Stemmer;
|
||||
use Wamania\Snowball\StemmerFactory;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Language support class for the Finder indexer package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Language
|
||||
{
|
||||
/**
|
||||
* Language support instances container.
|
||||
*
|
||||
* @var Language[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* Language locale of the class
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $language;
|
||||
|
||||
/**
|
||||
* Spacer to use between terms
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $spacer = ' ';
|
||||
|
||||
/**
|
||||
* The stemmer object.
|
||||
*
|
||||
* @var Stemmer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $stemmer = null;
|
||||
|
||||
/**
|
||||
* Method to construct the language object.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($locale = null)
|
||||
{
|
||||
if ($locale !== null) {
|
||||
$this->language = $locale;
|
||||
}
|
||||
|
||||
// Use our generic language handler if no language is set
|
||||
if ($this->language === null) {
|
||||
$this->language = '*';
|
||||
}
|
||||
|
||||
try {
|
||||
foreach (StemmerFactory::LANGS as $classname => $isoCodes) {
|
||||
if (\in_array($this->language, $isoCodes)) {
|
||||
$this->stemmer = StemmerFactory::create($this->language);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (NotFoundException $e) {
|
||||
// We don't have a stemmer for the language
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a language support object.
|
||||
*
|
||||
* @param string $language The language of the support object.
|
||||
*
|
||||
* @return Language A Language instance.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getInstance($language)
|
||||
{
|
||||
if (isset(self::$instances[$language])) {
|
||||
return self::$instances[$language];
|
||||
}
|
||||
|
||||
$locale = '*';
|
||||
|
||||
if ($language !== '*') {
|
||||
$locale = Helper::getPrimaryLanguage($language);
|
||||
$class = '\\Joomla\\Component\\Finder\\Administrator\\Indexer\\Language\\' . ucfirst($locale);
|
||||
|
||||
if (class_exists($class)) {
|
||||
self::$instances[$language] = new $class();
|
||||
|
||||
return self::$instances[$language];
|
||||
}
|
||||
}
|
||||
|
||||
self::$instances[$language] = new self($locale);
|
||||
|
||||
return self::$instances[$language];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to tokenise a text string.
|
||||
*
|
||||
* @param string $input The input to tokenise.
|
||||
*
|
||||
* @return array An array of term strings.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function tokenise($input)
|
||||
{
|
||||
$quotes = html_entity_decode('‘’'', ENT_QUOTES, 'UTF-8');
|
||||
|
||||
/*
|
||||
* Parsing the string input into terms is a multi-step process.
|
||||
*
|
||||
* Regexes:
|
||||
* 1. Remove everything except letters, numbers, quotes, apostrophe, plus, dash, period, and comma.
|
||||
* 2. Remove plus, dash, and comma characters located before letter characters.
|
||||
* 3. Remove plus, dash, period, and comma characters located after other characters.
|
||||
* 4. Remove plus, period, and comma characters enclosed in alphabetical characters. Ungreedy.
|
||||
* 5. Remove orphaned apostrophe, plus, dash, period, and comma characters.
|
||||
* 6. Remove orphaned quote characters.
|
||||
* 7. Replace the assorted single quotation marks with the ASCII standard single quotation.
|
||||
* 8. Remove multiple space characters and replaces with a single space.
|
||||
*/
|
||||
$input = StringHelper::strtolower($input);
|
||||
$input = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,]+#mui', ' ', $input);
|
||||
$input = preg_replace('#(^|\s)[+-,]+([\pL\pM]+)#mui', ' $1', $input);
|
||||
$input = preg_replace('#([\pL\pM\pN]+)[+-.,]+(\s|$)#mui', '$1 ', $input);
|
||||
$input = preg_replace('#([\pL\pM]+)[+.,]+([\pL\pM]+)#muiU', '$1 $2', $input);
|
||||
$input = preg_replace('#(^|\s)[\'+-.,]+(\s|$)#mui', ' ', $input);
|
||||
$input = preg_replace('#(^|\s)[\p{Pi}\p{Pf}]+(\s|$)#mui', ' ', $input);
|
||||
$input = preg_replace('#[' . $quotes . ']+#mui', '\'', $input);
|
||||
$input = preg_replace('#\s+#mui', ' ', $input);
|
||||
$input = trim($input);
|
||||
|
||||
// Explode the normalized string to get the terms.
|
||||
$terms = explode(' ', $input);
|
||||
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to stem a token.
|
||||
*
|
||||
* @param string $token The token to stem.
|
||||
*
|
||||
* @return string The stemmed token.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function stem($token)
|
||||
{
|
||||
if ($this->stemmer !== null) {
|
||||
return $this->stemmer->stem($token);
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
934
administrator/components/com_finder/src/Indexer/Language/El.php
Normal file
934
administrator/components/com_finder/src/Indexer/Language/El.php
Normal file
@ -0,0 +1,934 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* The Greek stemmer was adapted for Joomla! 4 by Nicholas K. Dionysopoulos <nicholas@akeebabackup.com>. This is
|
||||
* derivative work, based on the Greek stemmer for Drupal, see
|
||||
* https://github.com/magaras/greek_stemmer/blob/master/mod_stemmer.php
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer\Language;
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Language;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Greek language support class for the Finder indexer package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class El extends Language
|
||||
{
|
||||
/**
|
||||
* Language locale of the class
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $language = 'el';
|
||||
|
||||
/**
|
||||
* Method to construct the language object.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($locale = null)
|
||||
{
|
||||
// Override parent constructor since we don't need to load an external stemmer
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to tokenise a text string. It takes into account the odd punctuation commonly used in Greek text, mapping
|
||||
* it to ASCII punctuation.
|
||||
*
|
||||
* Reference: http://www.teicrete.gr/users/kutrulis/Glosika/Stixi.htm
|
||||
*
|
||||
* @param string $input The input to tokenise.
|
||||
*
|
||||
* @return array An array of term strings.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function tokenise($input)
|
||||
{
|
||||
// Replace Greek calligraphic double quotes (various styles) to dumb double quotes
|
||||
$input = str_replace(['“', '”', '„', '«' ,'»'], '"', $input);
|
||||
|
||||
// Replace Greek calligraphic single quotes (various styles) to dumb single quotes
|
||||
$input = str_replace(['‘','’','‚'], "'", $input);
|
||||
|
||||
// Replace the middle dot (ano teleia) with a comma, adequate for the purpose of stemming
|
||||
$input = str_replace('·', ',', $input);
|
||||
|
||||
// Dot and dash (τελεία και παύλα), used to denote the end of a context at the end of a paragraph.
|
||||
$input = str_replace('.–', '.', $input);
|
||||
|
||||
// Ellipsis, two styles (separate dots or single glyph)
|
||||
$input = str_replace(['...', '…'], '.', $input);
|
||||
|
||||
// Cross. Marks the death date of a person. Removed.
|
||||
$input = str_replace('†', '', $input);
|
||||
|
||||
// Star. Reference, supposition word (in philology), birth date of a person.
|
||||
$input = str_replace('*', '', $input);
|
||||
|
||||
// Paragraph. Indicates change of subject.
|
||||
$input = str_replace('§', '.', $input);
|
||||
|
||||
// Plus/minus. Shows approximation. Not relevant for the stemmer, hence its conversion to a space.
|
||||
$input = str_replace('±', ' ', $input);
|
||||
|
||||
return parent::tokenise($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to stem a token.
|
||||
*
|
||||
* @param string $token The token to stem.
|
||||
*
|
||||
* @return string The stemmed token.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function stem($token)
|
||||
{
|
||||
$token = $this->toUpperCase($token, $wCase);
|
||||
|
||||
// Stop-word removal
|
||||
$stop_words = '/^(ΕΚΟ|ΑΒΑ|ΑΓΑ|ΑΓΗ|ΑΓΩ|ΑΔΗ|ΑΔΩ|ΑΕ|ΑΕΙ|ΑΘΩ|ΑΙ|ΑΙΚ|ΑΚΗ|ΑΚΟΜΑ|ΑΚΟΜΗ|ΑΚΡΙΒΩΣ|ΑΛΑ|ΑΛΗΘΕΙΑ|ΑΛΗΘΙΝΑ|ΑΛΛΑΧΟΥ|ΑΛΛΙΩΣ|ΑΛΛΙΩΤΙΚΑ|'
|
||||
. 'ΑΛΛΟΙΩΣ|ΑΛΛΟΙΩΤΙΚΑ|ΑΛΛΟΤΕ|ΑΛΤ|ΑΛΩ|ΑΜΑ|ΑΜΕ|ΑΜΕΣΑ|ΑΜΕΣΩΣ|ΑΜΩ|ΑΝ|ΑΝΑ|ΑΝΑΜΕΣΑ|ΑΝΑΜΕΤΑΞΥ|ΑΝΕΥ|ΑΝΤΙ|ΑΝΤΙΠΕΡΑ|ΑΝΤΙΣ|ΑΝΩ|ΑΝΩΤΕΡΩ|ΑΞΑΦΝΑ|'
|
||||
. 'ΑΠ|ΑΠΕΝΑΝΤΙ|ΑΠΟ|ΑΠΟΨΕ|ΑΠΩ|ΑΡΑ|ΑΡΑΓΕ|ΑΡΕ|ΑΡΚ|ΑΡΚΕΤΑ|ΑΡΛ|ΑΡΜ|ΑΡΤ|ΑΡΥ|ΑΡΩ|ΑΣ|ΑΣΑ|ΑΣΟ|ΑΤΑ|ΑΤΕ|ΑΤΗ|ΑΤΙ|ΑΤΜ|ΑΤΟ|ΑΥΡΙΟ|ΑΦΗ|ΑΦΟΤΟΥ|ΑΦΟΥ|'
|
||||
. 'ΑΧ|ΑΧΕ|ΑΧΟ|ΑΨΑ|ΑΨΕ|ΑΨΗ|ΑΨΥ|ΑΩΕ|ΑΩΟ|ΒΑΝ|ΒΑΤ|ΒΑΧ|ΒΕΑ|ΒΕΒΑΙΟΤΑΤΑ|ΒΗΞ|ΒΙΑ|ΒΙΕ|ΒΙΗ|ΒΙΟ|ΒΟΗ|ΒΟΩ|ΒΡΕ|ΓΑ|ΓΑΒ|ΓΑΡ|ΓΕΝ|ΓΕΣ||ΓΗ|ΓΗΝ|ΓΙ|ΓΙΑ|'
|
||||
. 'ΓΙΕ|ΓΙΝ|ΓΙΟ|ΓΚΙ|ΓΙΑΤΙ|ΓΚΥ|ΓΟΗ|ΓΟΟ|ΓΡΗΓΟΡΑ|ΓΡΙ|ΓΡΥ|ΓΥΗ|ΓΥΡΩ|ΔΑ|ΔΕ|ΔΕΗ|ΔΕΙ|ΔΕΝ|ΔΕΣ|ΔΗ|ΔΗΘΕΝ|ΔΗΛΑΔΗ|ΔΗΩ|ΔΙ|ΔΙΑ|ΔΙΑΡΚΩΣ|ΔΙΟΛΟΥ|ΔΙΣ|'
|
||||
. 'ΔΙΧΩΣ|ΔΟΛ|ΔΟΝ|ΔΡΑ|ΔΡΥ|ΔΡΧ|ΔΥΕ|ΔΥΟ|ΔΩ|ΕΑΜ|ΕΑΝ|ΕΑΡ|ΕΘΗ|ΕΙ|ΕΙΔΕΜΗ|ΕΙΘΕ|ΕΙΜΑΙ|ΕΙΜΑΣΤΕ|ΕΙΝΑΙ|ΕΙΣ|ΕΙΣΑΙ|ΕΙΣΑΣΤΕ|ΕΙΣΤΕ|ΕΙΤΕ|ΕΙΧΑ|ΕΙΧΑΜΕ|'
|
||||
. 'ΕΙΧΑΝ|ΕΙΧΑΤΕ|ΕΙΧΕ|ΕΙΧΕΣ|ΕΚ|ΕΚΕΙ|ΕΛΑ|ΕΛΙ|ΕΜΠ|ΕΝ|ΕΝΤΕΛΩΣ|ΕΝΤΟΣ|ΕΝΤΩΜΕΤΑΞΥ|ΕΝΩ|ΕΞ|ΕΞΑΦΝΑ|ΕΞΙ|ΕΞΙΣΟΥ|ΕΞΩ|ΕΟΚ|ΕΠΑΝΩ|ΕΠΕΙΔΗ|ΕΠΕΙΤΑ|ΕΠΗ|'
|
||||
. 'ΕΠΙ|ΕΠΙΣΗΣ|ΕΠΟΜΕΝΩΣ|ΕΡΑ|ΕΣ|ΕΣΑΣ|ΕΣΕ|ΕΣΕΙΣ|ΕΣΕΝΑ|ΕΣΗ|ΕΣΤΩ|ΕΣΥ|ΕΣΩ|ΕΤΙ|ΕΤΣΙ|ΕΥ|ΕΥΑ|ΕΥΓΕ|ΕΥΘΥΣ|ΕΥΤΥΧΩΣ|ΕΦΕ|ΕΦΕΞΗΣ|ΕΦΤ|ΕΧΕ|ΕΧΕΙ|'
|
||||
. 'ΕΧΕΙΣ|ΕΧΕΤΕ|ΕΧΘΕΣ|ΕΧΟΜΕ|ΕΧΟΥΜΕ|ΕΧΟΥΝ|ΕΧΤΕΣ|ΕΧΩ|ΕΩΣ|ΖΕΑ|ΖΕΗ|ΖΕΙ|ΖΕΝ|ΖΗΝ|ΖΩ|Η|ΗΔΗ|ΗΔΥ|ΗΘΗ|ΗΛΟ|ΗΜΙ|ΗΠΑ|ΗΣΑΣΤΕ|ΗΣΟΥΝ|ΗΤΑ|ΗΤΑΝ|ΗΤΑΝΕ|'
|
||||
. 'ΗΤΟΙ|ΗΤΤΟΝ|ΗΩ|ΘΑ|ΘΥΕ|ΘΩΡ|Ι|ΙΑ|ΙΒΟ|ΙΔΗ|ΙΔΙΩΣ|ΙΕ|ΙΙ|ΙΙΙ|ΙΚΑ|ΙΛΟ|ΙΜΑ|ΙΝΑ|ΙΝΩ|ΙΞΕ|ΙΞΟ|ΙΟ|ΙΟΙ|ΙΣΑ|ΙΣΑΜΕ|ΙΣΕ|ΙΣΗ|ΙΣΙΑ|ΙΣΟ|ΙΣΩΣ|ΙΩΒ|ΙΩΝ|'
|
||||
. 'ΙΩΣ|ΙΑΝ|ΚΑΘ|ΚΑΘΕ|ΚΑΘΕΤΙ|ΚΑΘΟΛΟΥ|ΚΑΘΩΣ|ΚΑΙ|ΚΑΝ|ΚΑΠΟΤΕ|ΚΑΠΟΥ|ΚΑΠΩΣ|ΚΑΤ|ΚΑΤΑ|ΚΑΤΙ|ΚΑΤΙΤΙ|ΚΑΤΟΠΙΝ|ΚΑΤΩ|ΚΑΩ|ΚΒΟ|ΚΕΑ|ΚΕΙ|ΚΕΝ|ΚΙ|ΚΙΜ|'
|
||||
. 'ΚΙΟΛΑΣ|ΚΙΤ|ΚΙΧ|ΚΚΕ|ΚΛΙΣΕ|ΚΛΠ|ΚΟΚ|ΚΟΝΤΑ|ΚΟΧ|ΚΤΛ|ΚΥΡ|ΚΥΡΙΩΣ|ΚΩ|ΚΩΝ|ΛΑ|ΛΕΑ|ΛΕΝ|ΛΕΟ|ΛΙΑ|ΛΙΓΑΚΙ|ΛΙΓΟΥΛΑΚΙ|ΛΙΓΟ|ΛΙΓΩΤΕΡΟ|ΛΙΟ|ΛΙΡ|ΛΟΓΩ|'
|
||||
. 'ΛΟΙΠΑ|ΛΟΙΠΟΝ|ΛΟΣ|ΛΣ|ΛΥΩ|ΜΑ|ΜΑΖΙ|ΜΑΚΑΡΙ|ΜΑΛΙΣΤΑ|ΜΑΛΛΟΝ|ΜΑΝ|ΜΑΞ|ΜΑΣ|ΜΑΤ|ΜΕ|ΜΕΘΑΥΡΙΟ|ΜΕΙ|ΜΕΙΟΝ|ΜΕΛ|ΜΕΛΕΙ|ΜΕΛΛΕΤΑΙ|ΜΕΜΙΑΣ|ΜΕΝ|ΜΕΣ|'
|
||||
. 'ΜΕΣΑ|ΜΕΤ|ΜΕΤΑ|ΜΕΤΑΞΥ|ΜΕΧΡΙ|ΜΗ|ΜΗΔΕ|ΜΗΝ|ΜΗΠΩΣ|ΜΗΤΕ|ΜΙ|ΜΙΞ|ΜΙΣ|ΜΜΕ|ΜΝΑ|ΜΟΒ|ΜΟΛΙΣ|ΜΟΛΟΝΟΤΙ|ΜΟΝΑΧΑ|ΜΟΝΟΜΙΑΣ|ΜΙΑ|ΜΟΥ|ΜΠΑ|ΜΠΟΡΕΙ|'
|
||||
. 'ΜΠΟΡΟΥΝ|ΜΠΡΑΒΟ|ΜΠΡΟΣ|ΜΠΩ|ΜΥ|ΜΥΑ|ΜΥΝ|ΝΑ|ΝΑΕ|ΝΑΙ|ΝΑΟ|ΝΔ|ΝΕΐ|ΝΕΑ|ΝΕΕ|ΝΕΟ|ΝΙ|ΝΙΑ|ΝΙΚ|ΝΙΛ|ΝΙΝ|ΝΙΟ|ΝΤΑ|ΝΤΕ|ΝΤΙ|ΝΤΟ|ΝΥΝ|ΝΩΕ|ΝΩΡΙΣ|ΞΑΝΑ|'
|
||||
. 'ΞΑΦΝΙΚΑ|ΞΕΩ|ΞΙ|Ο|ΟΑ|ΟΑΠ|ΟΔΟ|ΟΕ|ΟΖΟ|ΟΗΕ|ΟΙ|ΟΙΑ|ΟΙΗ|ΟΚΑ|ΟΛΟΓΥΡΑ|ΟΛΟΝΕΝ|ΟΛΟΤΕΛΑ|ΟΛΩΣΔΙΟΛΟΥ|ΟΜΩΣ|ΟΝ|ΟΝΕ|ΟΝΟ|ΟΠΑ|ΟΠΕ|ΟΠΗ|ΟΠΟ|'
|
||||
. 'ΟΠΟΙΑΔΗΠΟΤΕ|ΟΠΟΙΑΝΔΗΠΟΤΕ|ΟΠΟΙΑΣΔΗΠΟΤΕ|ΟΠΟΙΔΗΠΟΤΕ|ΟΠΟΙΕΣΔΗΠΟΤΕ|ΟΠΟΙΟΔΗΠΟΤΕ|ΟΠΟΙΟΝΔΗΠΟΤΕ|ΟΠΟΙΟΣΔΗΠΟΤΕ|ΟΠΟΙΟΥΔΗΠΟΤΕ|ΟΠΟΙΟΥΣΔΗΠΟΤΕ|'
|
||||
. 'ΟΠΟΙΩΝΔΗΠΟΤΕ|ΟΠΟΤΕΔΗΠΟΤΕ|ΟΠΟΥ|ΟΠΟΥΔΗΠΟΤΕ|ΟΠΩΣ|ΟΡΑ|ΟΡΕ|ΟΡΗ|ΟΡΟ|ΟΡΦ|ΟΡΩ|ΟΣΑ|ΟΣΑΔΗΠΟΤΕ|ΟΣΕ|ΟΣΕΣΔΗΠΟΤΕ|ΟΣΗΔΗΠΟΤΕ|ΟΣΗΝΔΗΠΟΤΕ|'
|
||||
. 'ΟΣΗΣΔΗΠΟΤΕ|ΟΣΟΔΗΠΟΤΕ|ΟΣΟΙΔΗΠΟΤΕ|ΟΣΟΝΔΗΠΟΤΕ|ΟΣΟΣΔΗΠΟΤΕ|ΟΣΟΥΔΗΠΟΤΕ|ΟΣΟΥΣΔΗΠΟΤΕ|ΟΣΩΝΔΗΠΟΤΕ|ΟΤΑΝ|ΟΤΕ|ΟΤΙ|ΟΤΙΔΗΠΟΤΕ|ΟΥ|ΟΥΔΕ|ΟΥΚ|ΟΥΣ|'
|
||||
. 'ΟΥΤΕ|ΟΥΦ|ΟΧΙ|ΟΨΑ|ΟΨΕ|ΟΨΗ|ΟΨΙ|ΟΨΟ|ΠΑ|ΠΑΛΙ|ΠΑΝ|ΠΑΝΤΟΤΕ|ΠΑΝΤΟΥ|ΠΑΝΤΩΣ|ΠΑΠ|ΠΑΡ|ΠΑΡΑ|ΠΕΙ|ΠΕΡ|ΠΕΡΑ|ΠΕΡΙ|ΠΕΡΙΠΟΥ|ΠΕΡΣΙ|ΠΕΡΥΣΙ|ΠΕΣ|ΠΙ|'
|
||||
. 'ΠΙΑ|ΠΙΘΑΝΟΝ|ΠΙΚ|ΠΙΟ|ΠΙΣΩ|ΠΙΤ|ΠΙΩ|ΠΛΑΙ|ΠΛΕΟΝ|ΠΛΗΝ|ΠΛΩ|ΠΜ|ΠΟΑ|ΠΟΕ|ΠΟΛ|ΠΟΛΥ|ΠΟΠ|ΠΟΤΕ|ΠΟΥ|ΠΟΥΘΕ|ΠΟΥΘΕΝΑ|ΠΡΕΠΕΙ|ΠΡΙ|ΠΡΙΝ|ΠΡΟ|'
|
||||
. 'ΠΡΟΚΕΙΜΕΝΟΥ|ΠΡΟΚΕΙΤΑΙ|ΠΡΟΠΕΡΣΙ|ΠΡΟΣ|ΠΡΟΤΟΥ|ΠΡΟΧΘΕΣ|ΠΡΟΧΤΕΣ|ΠΡΩΤΥΤΕΡΑ|ΠΥΑ|ΠΥΞ|ΠΥΟ|ΠΥΡ|ΠΧ|ΠΩ|ΠΩΛ|ΠΩΣ|ΡΑ|ΡΑΙ|ΡΑΠ|ΡΑΣ|ΡΕ|ΡΕΑ|ΡΕΕ|ΡΕΙ|'
|
||||
. 'ΡΗΣ|ΡΘΩ|ΡΙΟ|ΡΟ|ΡΟΐ|ΡΟΕ|ΡΟΖ|ΡΟΗ|ΡΟΘ|ΡΟΙ|ΡΟΚ|ΡΟΛ|ΡΟΝ|ΡΟΣ|ΡΟΥ|ΣΑΙ|ΣΑΝ|ΣΑΟ|ΣΑΣ|ΣΕ|ΣΕΙΣ|ΣΕΚ|ΣΕΞ|ΣΕΡ|ΣΕΤ|ΣΕΦ|ΣΗΜΕΡΑ|ΣΙ|ΣΙΑ|ΣΙΓΑ|ΣΙΚ|'
|
||||
. 'ΣΙΧ|ΣΚΙ|ΣΟΙ|ΣΟΚ|ΣΟΛ|ΣΟΝ|ΣΟΣ|ΣΟΥ|ΣΡΙ|ΣΤΑ|ΣΤΗ|ΣΤΗΝ|ΣΤΗΣ|ΣΤΙΣ|ΣΤΟ|ΣΤΟΝ|ΣΤΟΥ|ΣΤΟΥΣ|ΣΤΩΝ|ΣΥ|ΣΥΓΧΡΟΝΩΣ|ΣΥΝ|ΣΥΝΑΜΑ|ΣΥΝΕΠΩΣ|ΣΥΝΗΘΩΣ|'
|
||||
. 'ΣΧΕΔΟΝ|ΣΩΣΤΑ|ΤΑ|ΤΑΔΕ|ΤΑΚ|ΤΑΝ|ΤΑΟ|ΤΑΥ|ΤΑΧΑ|ΤΑΧΑΤΕ|ΤΕ|ΤΕΙ|ΤΕΛ|ΤΕΛΙΚΑ|ΤΕΛΙΚΩΣ|ΤΕΣ|ΤΕΤ|ΤΖΟ|ΤΗ|ΤΗΛ|ΤΗΝ|ΤΗΣ|ΤΙ|ΤΙΚ|ΤΙΜ|ΤΙΠΟΤΑ|ΤΙΠΟΤΕ|'
|
||||
. 'ΤΙΣ|ΤΝΤ|ΤΟ|ΤΟΙ|ΤΟΚ|ΤΟΜ|ΤΟΝ|ΤΟΠ|ΤΟΣ|ΤΟΣ?Ν|ΤΟΣΑ|ΤΟΣΕΣ|ΤΟΣΗ|ΤΟΣΗΝ|ΤΟΣΗΣ|ΤΟΣΟ|ΤΟΣΟΙ|ΤΟΣΟΝ|ΤΟΣΟΣ|ΤΟΣΟΥ|ΤΟΣΟΥΣ|ΤΟΤΕ|ΤΟΥ|ΤΟΥΛΑΧΙΣΤΟ|'
|
||||
. 'ΤΟΥΛΑΧΙΣΤΟΝ|ΤΟΥΣ|ΤΣ|ΤΣΑ|ΤΣΕ|ΤΥΧΟΝ|ΤΩ|ΤΩΝ|ΤΩΡΑ|ΥΑΣ|ΥΒΑ|ΥΒΟ|ΥΙΕ|ΥΙΟ|ΥΛΑ|ΥΛΗ|ΥΝΙ|ΥΠ|ΥΠΕΡ|ΥΠΟ|ΥΠΟΨΗ|ΥΠΟΨΙΝ|ΥΣΤΕΡΑ|ΥΦΗ|ΥΨΗ|ΦΑ|ΦΑΐ|ΦΑΕ|'
|
||||
. 'ΦΑΝ|ΦΑΞ|ΦΑΣ|ΦΑΩ|ΦΕΖ|ΦΕΙ|ΦΕΤΟΣ|ΦΕΥ|ΦΙ|ΦΙΛ|ΦΙΣ|ΦΟΞ|ΦΠΑ|ΦΡΙ|ΧΑ|ΧΑΗ|ΧΑΛ|ΧΑΝ|ΧΑΦ|ΧΕ|ΧΕΙ|ΧΘΕΣ|ΧΙ|ΧΙΑ|ΧΙΛ|ΧΙΟ|ΧΛΜ|ΧΜ|ΧΟΗ|ΧΟΛ|ΧΡΩ|ΧΤΕΣ|'
|
||||
. 'ΧΩΡΙΣ|ΧΩΡΙΣΤΑ|ΨΕΣ|ΨΗΛΑ|ΨΙ|ΨΙΤ|Ω|ΩΑ|ΩΑΣ|ΩΔΕ|ΩΕΣ|ΩΘΩ|ΩΜΑ|ΩΜΕ|ΩΝ|ΩΟ|ΩΟΝ|ΩΟΥ|ΩΣ|ΩΣΑΝ|ΩΣΗ|ΩΣΟΤΟΥ|ΩΣΠΟΥ|ΩΣΤΕ|ΩΣΤΟΣΟ|ΩΤΑ|ΩΧ|ΩΩΝ)$/';
|
||||
|
||||
if (preg_match($stop_words, $token)) {
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Vowels
|
||||
$v = '(Α|Ε|Η|Ι|Ο|Υ|Ω)';
|
||||
|
||||
// Vowels without Y
|
||||
$v2 = '(Α|Ε|Η|Ι|Ο|Ω)';
|
||||
|
||||
$test1 = true;
|
||||
|
||||
// Step S1. 14 stems
|
||||
$re = '/^(.+?)(ΙΖΑ|ΙΖΕΣ|ΙΖΕ|ΙΖΑΜΕ|ΙΖΑΤΕ|ΙΖΑΝ|ΙΖΑΝΕ|ΙΖΩ|ΙΖΕΙΣ|ΙΖΕΙ|ΙΖΟΥΜΕ|ΙΖΕΤΕ|ΙΖΟΥΝ|ΙΖΟΥΝΕ)$/';
|
||||
$exceptS1 = '/^(ΑΝΑΜΠΑ|ΕΜΠΑ|ΕΠΑ|ΞΑΝΑΠΑ|ΠΑ|ΠΕΡΙΠΑ|ΑΘΡΟ|ΣΥΝΑΘΡΟ|ΔΑΝΕ)$/';
|
||||
$exceptS2 = '/^(ΜΑΡΚ|ΚΟΡΝ|ΑΜΠΑΡ|ΑΡΡ|ΒΑΘΥΡΙ|ΒΑΡΚ|Β|ΒΟΛΒΟΡ|ΓΚΡ|ΓΛΥΚΟΡ|ΓΛΥΚΥΡ|ΙΜΠ|Λ|ΛΟΥ|ΜΑΡ|Μ|ΠΡ|ΜΠΡ|ΠΟΛΥΡ|Π|Ρ|ΠΙΠΕΡΟΡ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= 'I';
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= 'IΖ';
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S2. 7 stems
|
||||
$re = '/^(.+?)(ΩΘΗΚΑ|ΩΘΗΚΕΣ|ΩΘΗΚΕ|ΩΘΗΚΑΜΕ|ΩΘΗΚΑΤΕ|ΩΘΗΚΑΝ|ΩΘΗΚΑΝΕ)$/';
|
||||
$exceptS1 = '/^(ΑΛ|ΒΙ|ΕΝ|ΥΨ|ΛΙ|ΖΩ|Σ|Χ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= 'ΩΝ';
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S3. 7 stems
|
||||
$re = '/^(.+?)(ΙΣΑ|ΙΣΕΣ|ΙΣΕ|ΙΣΑΜΕ|ΙΣΑΤΕ|ΙΣΑΝ|ΙΣΑΝΕ)$/';
|
||||
$exceptS1 = '/^(ΑΝΑΜΠΑ|ΑΘΡΟ|ΕΜΠΑ|ΕΣΕ|ΕΣΩΚΛΕ|ΕΠΑ|ΞΑΝΑΠΑ|ΕΠΕ|ΠΕΡΙΠΑ|ΑΘΡΟ|ΣΥΝΑΘΡΟ|ΔΑΝΕ|ΚΛΕ|ΧΑΡΤΟΠΑ|ΕΞΑΡΧΑ|ΜΕΤΕΠΕ|ΑΠΟΚΛΕ|ΑΠΕΚΛΕ|ΕΚΛΕ|ΠΕ|ΠΕΡΙΠΑ)$/';
|
||||
$exceptS2 = '/^(ΑΝ|ΑΦ|ΓΕ|ΓΙΓΑΝΤΟΑΦ|ΓΚΕ|ΔΗΜΟΚΡΑΤ|ΚΟΜ|ΓΚ|Μ|Π|ΠΟΥΚΑΜ|ΟΛΟ|ΛΑΡ)$/';
|
||||
|
||||
if ($token == "ΙΣΑ") {
|
||||
$token = "ΙΣ";
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= 'Ι';
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= 'ΙΣ';
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S4. 7 stems
|
||||
$re = '/^(.+?)(ΙΣΩ|ΙΣΕΙΣ|ΙΣΕΙ|ΙΣΟΥΜΕ|ΙΣΕΤΕ|ΙΣΟΥΝ|ΙΣΟΥΝΕ)$/';
|
||||
$exceptS1 = '/^(ΑΝΑΜΠΑ|ΕΜΠΑ|ΕΣΕ|ΕΣΩΚΛΕ|ΕΠΑ|ΞΑΝΑΠΑ|ΕΠΕ|ΠΕΡΙΠΑ|ΑΘΡΟ|ΣΥΝΑΘΡΟ|ΔΑΝΕ|ΚΛΕ|ΧΑΡΤΟΠΑ|ΕΞΑΡΧΑ|ΜΕΤΕΠΕ|ΑΠΟΚΛΕ|ΑΠΕΚΛΕ|ΕΚΛΕ|ΠΕ|ΠΕΡΙΠΑ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= 'Ι';
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S5. 11 stems
|
||||
$re = '/^(.+?)(ΙΣΤΟΣ|ΙΣΤΟΥ|ΙΣΤΟ|ΙΣΤΕ|ΙΣΤΟΙ|ΙΣΤΩΝ|ΙΣΤΟΥΣ|ΙΣΤΗ|ΙΣΤΗΣ|ΙΣΤΑ|ΙΣΤΕΣ)$/';
|
||||
$exceptS1 = '/^(Μ|Π|ΑΠ|ΑΡ|ΗΔ|ΚΤ|ΣΚ|ΣΧ|ΥΨ|ΦΑ|ΧΡ|ΧΤ|ΑΚΤ|ΑΟΡ|ΑΣΧ|ΑΤΑ|ΑΧΝ|ΑΧΤ|ΓΕΜ|ΓΥΡ|ΕΜΠ|ΕΥΠ|ΕΧΘ|ΗΦΑ|ΚΑΘ|ΚΑΚ|ΚΥΛ|ΛΥΓ|ΜΑΚ|ΜΕΓ|ΤΑΧ|ΦΙΛ|ΧΩΡ)$/';
|
||||
$exceptS2 = '/^(ΔΑΝΕ|ΣΥΝΑΘΡΟ|ΚΛΕ|ΣΕ|ΕΣΩΚΛΕ|ΑΣΕ|ΠΛΕ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= 'ΙΣΤ';
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= 'Ι';
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S6. 6 stems
|
||||
$re = '/^(.+?)(ΙΣΜΟ|ΙΣΜΟΙ|ΙΣΜΟΣ|ΙΣΜΟΥ|ΙΣΜΟΥΣ|ΙΣΜΩΝ)$/';
|
||||
$exceptS1 = '/^(ΑΓΝΩΣΤΙΚ|ΑΤΟΜΙΚ|ΓΝΩΣΤΙΚ|ΕΘΝΙΚ|ΕΚΛΕΚΤΙΚ|ΣΚΕΠΤΙΚ|ΤΟΠΙΚ)$/';
|
||||
$exceptS2 = '/^(ΣΕ|ΜΕΤΑΣΕ|ΜΙΚΡΟΣΕ|ΕΓΚΛΕ|ΑΠΟΚΛΕ)$/';
|
||||
$exceptS3 = '/^(ΔΑΝΕ|ΑΝΤΙΔΑΝΕ)$/';
|
||||
$exceptS4 = '/^(ΑΛΕΞΑΝΔΡΙΝ|ΒΥΖΑΝΤΙΝ|ΘΕΑΤΡΙΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token = str_replace('ΙΚ', "", $token);
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= "ΙΣΜ";
|
||||
}
|
||||
|
||||
if (preg_match($exceptS3, $token)) {
|
||||
$token .= "Ι";
|
||||
}
|
||||
|
||||
if (preg_match($exceptS4, $token)) {
|
||||
$token = str_replace('ΙΝ', "", $token);
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S7. 4 stems
|
||||
$re = '/^(.+?)(ΑΡΑΚΙ|ΑΡΑΚΙΑ|ΟΥΔΑΚΙ|ΟΥΔΑΚΙΑ)$/';
|
||||
$exceptS1 = '/^(Σ|Χ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= "AΡΑΚ";
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S8. 8 stems
|
||||
$re = '/^(.+?)(ΑΚΙ|ΑΚΙΑ|ΙΤΣΑ|ΙΤΣΑΣ|ΙΤΣΕΣ|ΙΤΣΩΝ|ΑΡΑΚΙ|ΑΡΑΚΙΑ)$/';
|
||||
$exceptS1 = '/^(ΑΝΘΡ|ΒΑΜΒ|ΒΡ|ΚΑΙΜ|ΚΟΝ|ΚΟΡ|ΛΑΒΡ|ΛΟΥΛ|ΜΕΡ|ΜΟΥΣΤ|ΝΑΓΚΑΣ|ΠΛ|Ρ|ΡΥ|Σ|ΣΚ|ΣΟΚ|ΣΠΑΝ|ΤΖ|ΦΑΡΜ|Χ|'
|
||||
. 'ΚΑΠΑΚ|ΑΛΙΣΦ|ΑΜΒΡ|ΑΝΘΡ|Κ|ΦΥΛ|ΚΑΤΡΑΠ|ΚΛΙΜ|ΜΑΛ|ΣΛΟΒ|Φ|ΣΦ|ΤΣΕΧΟΣΛΟΒ)$/';
|
||||
$exceptS2 = '/^(Β|ΒΑΛ|ΓΙΑΝ|ΓΛ|Ζ|ΗΓΟΥΜΕΝ|ΚΑΡΔ|ΚΟΝ|ΜΑΚΡΥΝ|ΝΥΦ|ΠΑΤΕΡ|Π|ΣΚ|ΤΟΣ|ΤΡΙΠΟΛ)$/';
|
||||
|
||||
// For words like ΠΛΟΥΣΙΟΚΟΡΙΤΣΑ, ΠΑΛΙΟΚΟΡΙΤΣΑ etc
|
||||
$exceptS3 = '/(ΚΟΡ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= "ΑΚ";
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= "ΙΤΣ";
|
||||
}
|
||||
|
||||
if (preg_match($exceptS3, $token)) {
|
||||
$token .= "ΙΤΣ";
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S9. 3 stems
|
||||
$re = '/^(.+?)(ΙΔΙΟ|ΙΔΙΑ|ΙΔΙΩΝ)$/';
|
||||
$exceptS1 = '/^(ΑΙΦΝ|ΙΡ|ΟΛΟ|ΨΑΛ)$/';
|
||||
$exceptS2 = '/(Ε|ΠΑΙΧΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= "ΙΔ";
|
||||
}
|
||||
|
||||
if (preg_match($exceptS2, $token)) {
|
||||
$token .= "ΙΔ";
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step S10. 4 stems
|
||||
$re = '/^(.+?)(ΙΣΚΟΣ|ΙΣΚΟΥ|ΙΣΚΟ|ΙΣΚΕ)$/';
|
||||
$exceptS1 = '/^(Δ|ΙΒ|ΜΗΝ|Ρ|ΦΡΑΓΚ|ΛΥΚ|ΟΒΕΛ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
|
||||
if (preg_match($exceptS1, $token)) {
|
||||
$token .= "ΙΣΚ";
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
// Step 1
|
||||
// step1list is used in Step 1. 41 stems
|
||||
$step1list = [];
|
||||
$step1list["ΦΑΓΙΑ"] = "ΦΑ";
|
||||
$step1list["ΦΑΓΙΟΥ"] = "ΦΑ";
|
||||
$step1list["ΦΑΓΙΩΝ"] = "ΦΑ";
|
||||
$step1list["ΣΚΑΓΙΑ"] = "ΣΚΑ";
|
||||
$step1list["ΣΚΑΓΙΟΥ"] = "ΣΚΑ";
|
||||
$step1list["ΣΚΑΓΙΩΝ"] = "ΣΚΑ";
|
||||
$step1list["ΟΛΟΓΙΟΥ"] = "ΟΛΟ";
|
||||
$step1list["ΟΛΟΓΙΑ"] = "ΟΛΟ";
|
||||
$step1list["ΟΛΟΓΙΩΝ"] = "ΟΛΟ";
|
||||
$step1list["ΣΟΓΙΟΥ"] = "ΣΟ";
|
||||
$step1list["ΣΟΓΙΑ"] = "ΣΟ";
|
||||
$step1list["ΣΟΓΙΩΝ"] = "ΣΟ";
|
||||
$step1list["ΤΑΤΟΓΙΑ"] = "ΤΑΤΟ";
|
||||
$step1list["ΤΑΤΟΓΙΟΥ"] = "ΤΑΤΟ";
|
||||
$step1list["ΤΑΤΟΓΙΩΝ"] = "ΤΑΤΟ";
|
||||
$step1list["ΚΡΕΑΣ"] = "ΚΡΕ";
|
||||
$step1list["ΚΡΕΑΤΟΣ"] = "ΚΡΕ";
|
||||
$step1list["ΚΡΕΑΤΑ"] = "ΚΡΕ";
|
||||
$step1list["ΚΡΕΑΤΩΝ"] = "ΚΡΕ";
|
||||
$step1list["ΠΕΡΑΣ"] = "ΠΕΡ";
|
||||
$step1list["ΠΕΡΑΤΟΣ"] = "ΠΕΡ";
|
||||
|
||||
// Added by Spyros. Also at $re in step1
|
||||
$step1list["ΠΕΡΑΤΗ"] = "ΠΕΡ";
|
||||
$step1list["ΠΕΡΑΤΑ"] = "ΠΕΡ";
|
||||
$step1list["ΠΕΡΑΤΩΝ"] = "ΠΕΡ";
|
||||
$step1list["ΤΕΡΑΣ"] = "ΤΕΡ";
|
||||
$step1list["ΤΕΡΑΤΟΣ"] = "ΤΕΡ";
|
||||
$step1list["ΤΕΡΑΤΑ"] = "ΤΕΡ";
|
||||
$step1list["ΤΕΡΑΤΩΝ"] = "ΤΕΡ";
|
||||
$step1list["ΦΩΣ"] = "ΦΩ";
|
||||
$step1list["ΦΩΤΟΣ"] = "ΦΩ";
|
||||
$step1list["ΦΩΤΑ"] = "ΦΩ";
|
||||
$step1list["ΦΩΤΩΝ"] = "ΦΩ";
|
||||
$step1list["ΚΑΘΕΣΤΩΣ"] = "ΚΑΘΕΣΤ";
|
||||
$step1list["ΚΑΘΕΣΤΩΤΟΣ"] = "ΚΑΘΕΣΤ";
|
||||
$step1list["ΚΑΘΕΣΤΩΤΑ"] = "ΚΑΘΕΣΤ";
|
||||
$step1list["ΚΑΘΕΣΤΩΤΩΝ"] = "ΚΑΘΕΣΤ";
|
||||
$step1list["ΓΕΓΟΝΟΣ"] = "ΓΕΓΟΝ";
|
||||
$step1list["ΓΕΓΟΝΟΤΟΣ"] = "ΓΕΓΟΝ";
|
||||
$step1list["ΓΕΓΟΝΟΤΑ"] = "ΓΕΓΟΝ";
|
||||
$step1list["ΓΕΓΟΝΟΤΩΝ"] = "ΓΕΓΟΝ";
|
||||
|
||||
$re = '/(.*)(ΦΑΓΙΑ|ΦΑΓΙΟΥ|ΦΑΓΙΩΝ|ΣΚΑΓΙΑ|ΣΚΑΓΙΟΥ|ΣΚΑΓΙΩΝ|ΟΛΟΓΙΟΥ|ΟΛΟΓΙΑ|ΟΛΟΓΙΩΝ|ΣΟΓΙΟΥ|ΣΟΓΙΑ|ΣΟΓΙΩΝ|ΤΑΤΟΓΙΑ|ΤΑΤΟΓΙΟΥ|ΤΑΤΟΓΙΩΝ|ΚΡΕΑΣ|ΚΡΕΑΤΟΣ|'
|
||||
. 'ΚΡΕΑΤΑ|ΚΡΕΑΤΩΝ|ΠΕΡΑΣ|ΠΕΡΑΤΟΣ|ΠΕΡΑΤΗ|ΠΕΡΑΤΑ|ΠΕΡΑΤΩΝ|ΤΕΡΑΣ|ΤΕΡΑΤΟΣ|ΤΕΡΑΤΑ|ΤΕΡΑΤΩΝ|ΦΩΣ|ΦΩΤΟΣ|ΦΩΤΑ|ΦΩΤΩΝ|ΚΑΘΕΣΤΩΣ|ΚΑΘΕΣΤΩΤΟΣ|'
|
||||
. 'ΚΑΘΕΣΤΩΤΑ|ΚΑΘΕΣΤΩΤΩΝ|ΓΕΓΟΝΟΣ|ΓΕΓΟΝΟΤΟΣ|ΓΕΓΟΝΟΤΑ|ΓΕΓΟΝΟΤΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$stem = $match[1];
|
||||
$suffix = $match[2];
|
||||
$token = $stem . (\array_key_exists($suffix, $step1list) ? $step1list[$suffix] : '');
|
||||
$test1 = false;
|
||||
}
|
||||
|
||||
// Step 2a. 2 stems
|
||||
$re = '/^(.+?)(ΑΔΕΣ|ΑΔΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1];
|
||||
$re = '/(ΟΚ|ΜΑΜ|ΜΑΝ|ΜΠΑΜΠ|ΠΑΤΕΡ|ΓΙΑΓΙ|ΝΤΑΝΤ|ΚΥΡ|ΘΕΙ|ΠΕΘΕΡ)$/';
|
||||
|
||||
if (!preg_match($re, $token)) {
|
||||
$token .= "ΑΔ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2b. 2 stems
|
||||
$re = '/^(.+?)(ΕΔΕΣ|ΕΔΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$exept2 = '/(ΟΠ|ΙΠ|ΕΜΠ|ΥΠ|ΓΗΠ|ΔΑΠ|ΚΡΑΣΠ|ΜΙΛ)$/';
|
||||
|
||||
if (preg_match($exept2, $token)) {
|
||||
$token .= 'ΕΔ';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2c
|
||||
$re = '/^(.+?)(ΟΥΔΕΣ|ΟΥΔΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
|
||||
$exept3 = '/(ΑΡΚ|ΚΑΛΙΑΚ|ΠΕΤΑΛ|ΛΙΧ|ΠΛΕΞ|ΣΚ|Σ|ΦΛ|ΦΡ|ΒΕΛ|ΛΟΥΛ|ΧΝ|ΣΠ|ΤΡΑΓ|ΦΕ)$/';
|
||||
|
||||
if (preg_match($exept3, $token)) {
|
||||
$token .= 'ΟΥΔ';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2d
|
||||
$re = '/^(.+?)(ΕΩΣ|ΕΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept4 = '/^(Θ|Δ|ΕΛ|ΓΑΛ|Ν|Π|ΙΔ|ΠΑΡ)$/';
|
||||
|
||||
if (preg_match($exept4, $token)) {
|
||||
$token .= 'Ε';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3
|
||||
$re = '/^(.+?)(ΙΑ|ΙΟΥ|ΙΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $fp)) {
|
||||
$stem = $fp[1];
|
||||
$token = $stem;
|
||||
$re = '/' . $v . '$/';
|
||||
$test1 = false;
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
$token = $stem . 'Ι';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4
|
||||
$re = '/^(.+?)(ΙΚΑ|ΙΚΟ|ΙΚΟΥ|ΙΚΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$re = '/' . $v . '$/';
|
||||
$exept5 = '/^(ΑΛ|ΑΔ|ΕΝΔ|ΑΜΑΝ|ΑΜΜΟΧΑΛ|ΗΘ|ΑΝΗΘ|ΑΝΤΙΔ|ΦΥΣ|ΒΡΩΜ|ΓΕΡ|ΕΞΩΔ|ΚΑΛΠ|ΚΑΛΛΙΝ|ΚΑΤΑΔ|ΜΟΥΛ|ΜΠΑΝ|ΜΠΑΓΙΑΤ|ΜΠΟΛ|ΜΠΟΣ|ΝΙΤ|ΞΙΚ|ΣΥΝΟΜΗΛ|ΠΕΤΣ|'
|
||||
. 'ΠΙΤΣ|ΠΙΚΑΝΤ|ΠΛΙΑΤΣ|ΠΟΣΤΕΛΝ|ΠΡΩΤΟΔ|ΣΕΡΤ|ΣΥΝΑΔ|ΤΣΑΜ|ΥΠΟΔ|ΦΙΛΟΝ|ΦΥΛΟΔ|ΧΑΣ)$/';
|
||||
|
||||
if (preg_match($re, $token) || preg_match($exept5, $token)) {
|
||||
$token .= 'ΙΚ';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5a
|
||||
$re = '/^(.+?)(ΑΜΕ)$/';
|
||||
$re2 = '/^(.+?)(ΑΓΑΜΕ|ΗΣΑΜΕ|ΟΥΣΑΜΕ|ΗΚΑΜΕ|ΗΘΗΚΑΜΕ)$/';
|
||||
|
||||
if ($token == "ΑΓΑΜΕ") {
|
||||
$token = "ΑΓΑΜ";
|
||||
}
|
||||
|
||||
if (preg_match($re2, $token)) {
|
||||
preg_match($re2, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
}
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept6 = '/^(ΑΝΑΠ|ΑΠΟΘ|ΑΠΟΚ|ΑΠΟΣΤ|ΒΟΥΒ|ΞΕΘ|ΟΥΛ|ΠΕΘ|ΠΙΚΡ|ΠΟΤ|ΣΙΧ|Χ)$/';
|
||||
|
||||
if (preg_match($exept6, $token)) {
|
||||
$token .= "ΑΜ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5b
|
||||
$re2 = '/^(.+?)(ΑΝΕ)$/';
|
||||
$re3 = '/^(.+?)(ΑΓΑΝΕ|ΗΣΑΝΕ|ΟΥΣΑΝΕ|ΙΟΝΤΑΝΕ|ΙΟΤΑΝΕ|ΙΟΥΝΤΑΝΕ|ΟΝΤΑΝΕ|ΟΤΑΝΕ|ΟΥΝΤΑΝΕ|ΗΚΑΝΕ|ΗΘΗΚΑΝΕ)$/';
|
||||
|
||||
if (preg_match($re3, $token)) {
|
||||
preg_match($re3, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$re3 = '/^(ΤΡ|ΤΣ)$/';
|
||||
|
||||
if (preg_match($re3, $token)) {
|
||||
$token .= "ΑΓΑΝ";
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match($re2, $token)) {
|
||||
preg_match($re2, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$re2 = '/' . $v2 . '$/';
|
||||
$exept7 = '/^(ΒΕΤΕΡ|ΒΟΥΛΚ|ΒΡΑΧΜ|Γ|ΔΡΑΔΟΥΜ|Θ|ΚΑΛΠΟΥΖ|ΚΑΣΤΕΛ|ΚΟΡΜΟΡ|ΛΑΟΠΛ|ΜΩΑΜΕΘ|Μ|ΜΟΥΣΟΥΛΜ|Ν|ΟΥΛ|Π|ΠΕΛΕΚ|ΠΛ|ΠΟΛΙΣ|ΠΟΡΤΟΛ|ΣΑΡΑΚΑΤΣ|ΣΟΥΛΤ|'
|
||||
. 'ΤΣΑΡΛΑΤ|ΟΡΦ|ΤΣΙΓΓ|ΤΣΟΠ|ΦΩΤΟΣΤΕΦ|Χ|ΨΥΧΟΠΛ|ΑΓ|ΟΡΦ|ΓΑΛ|ΓΕΡ|ΔΕΚ|ΔΙΠΛ|ΑΜΕΡΙΚΑΝ|ΟΥΡ|ΠΙΘ|ΠΟΥΡΙΤ|Σ|ΖΩΝΤ|ΙΚ|ΚΑΣΤ|ΚΟΠ|ΛΙΧ|ΛΟΥΘΗΡ|ΜΑΙΝΤ|'
|
||||
. 'ΜΕΛ|ΣΙΓ|ΣΠ|ΣΤΕΓ|ΤΡΑΓ|ΤΣΑΓ|Φ|ΕΡ|ΑΔΑΠ|ΑΘΙΓΓ|ΑΜΗΧ|ΑΝΙΚ|ΑΝΟΡΓ|ΑΠΗΓ|ΑΠΙΘ|ΑΤΣΙΓΓ|ΒΑΣ|ΒΑΣΚ|ΒΑΘΥΓΑΛ|ΒΙΟΜΗΧ|ΒΡΑΧΥΚ|ΔΙΑΤ|ΔΙΑΦ|ΕΝΟΡΓ|'
|
||||
. 'ΘΥΣ|ΚΑΠΝΟΒΙΟΜΗΧ|ΚΑΤΑΓΑΛ|ΚΛΙΒ|ΚΟΙΛΑΡΦ|ΛΙΒ|ΜΕΓΛΟΒΙΟΜΗΧ|ΜΙΚΡΟΒΙΟΜΗΧ|ΝΤΑΒ|ΞΗΡΟΚΛΙΒ|ΟΛΙΓΟΔΑΜ|ΟΛΟΓΑΛ|ΠΕΝΤΑΡΦ|ΠΕΡΗΦ|ΠΕΡΙΤΡ|ΠΛΑΤ|'
|
||||
. 'ΠΟΛΥΔΑΠ|ΠΟΛΥΜΗΧ|ΣΤΕΦ|ΤΑΒ|ΤΕΤ|ΥΠΕΡΗΦ|ΥΠΟΚΟΠ|ΧΑΜΗΛΟΔΑΠ|ΨΗΛΟΤΑΒ)$/';
|
||||
|
||||
if (preg_match($re2, $token) || preg_match($exept7, $token)) {
|
||||
$token .= "ΑΝ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5c
|
||||
$re3 = '/^(.+?)(ΕΤΕ)$/';
|
||||
$re4 = '/^(.+?)(ΗΣΕΤΕ)$/';
|
||||
|
||||
if (preg_match($re4, $token)) {
|
||||
preg_match($re4, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
}
|
||||
|
||||
if (preg_match($re3, $token)) {
|
||||
preg_match($re3, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$re3 = '/' . $v2 . '$/';
|
||||
$exept8 = '/(ΟΔ|ΑΙΡ|ΦΟΡ|ΤΑΘ|ΔΙΑΘ|ΣΧ|ΕΝΔ|ΕΥΡ|ΤΙΘ|ΥΠΕΡΘ|ΡΑΘ|ΕΝΘ|ΡΟΘ|ΣΘ|ΠΥΡ|ΑΙΝ|ΣΥΝΔ|ΣΥΝ|ΣΥΝΘ|ΧΩΡ|ΠΟΝ|ΒΡ|ΚΑΘ|ΕΥΘ|ΕΚΘ|ΝΕΤ|ΡΟΝ|ΑΡΚ|ΒΑΡ|ΒΟΛ|ΩΦΕΛ)$/';
|
||||
$exept9 = '/^(ΑΒΑΡ|ΒΕΝ|ΕΝΑΡ|ΑΒΡ|ΑΔ|ΑΘ|ΑΝ|ΑΠΛ|ΒΑΡΟΝ|ΝΤΡ|ΣΚ|ΚΟΠ|ΜΠΟΡ|ΝΙΦ|ΠΑΓ|ΠΑΡΑΚΑΛ|ΣΕΡΠ|ΣΚΕΛ|ΣΥΡΦ|ΤΟΚ|Υ|Δ|ΕΜ|ΘΑΡΡ|Θ)$/';
|
||||
|
||||
if (preg_match($re3, $token) || preg_match($exept8, $token) || preg_match($exept9, $token)) {
|
||||
$token .= "ΕΤ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5d
|
||||
$re = '/^(.+?)(ΟΝΤΑΣ|ΩΝΤΑΣ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept10 = '/^(ΑΡΧ)$/';
|
||||
$exept11 = '/(ΚΡΕ)$/';
|
||||
|
||||
if (preg_match($exept10, $token)) {
|
||||
$token .= "ΟΝΤ";
|
||||
}
|
||||
|
||||
if (preg_match($exept11, $token)) {
|
||||
$token .= "ΩΝΤ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5e
|
||||
$re = '/^(.+?)(ΟΜΑΣΤΕ|ΙΟΜΑΣΤΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept11 = '/^(ΟΝ)$/';
|
||||
|
||||
if (preg_match($exept11, $token)) {
|
||||
$token .= "ΟΜΑΣΤ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5f
|
||||
$re = '/^(.+?)(ΕΣΤΕ)$/';
|
||||
$re2 = '/^(.+?)(ΙΕΣΤΕ)$/';
|
||||
|
||||
if (preg_match($re2, $token)) {
|
||||
preg_match($re2, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$re2 = '/^(Π|ΑΠ|ΣΥΜΠ|ΑΣΥΜΠ|ΑΚΑΤΑΠ|ΑΜΕΤΑΜΦ)$/';
|
||||
|
||||
if (preg_match($re2, $token)) {
|
||||
$token .= "ΙΕΣΤ";
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept12 = '/^(ΑΛ|ΑΡ|ΕΚΤΕΛ|Ζ|Μ|Ξ|ΠΑΡΑΚΑΛ|ΠΡΟ|ΝΙΣ)$/';
|
||||
|
||||
if (preg_match($exept12, $token)) {
|
||||
$token .= "ΕΣΤ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5g
|
||||
$re = '/^(.+?)(ΗΚΑ|ΗΚΕΣ|ΗΚΕ)$/';
|
||||
$re2 = '/^(.+?)(ΗΘΗΚΑ|ΗΘΗΚΕΣ|ΗΘΗΚΕ)$/';
|
||||
|
||||
if (preg_match($re2, $token)) {
|
||||
preg_match($re2, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
}
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept13 = '/(ΣΚΩΛ|ΣΚΟΥΛ|ΝΑΡΘ|ΣΦ|ΟΘ|ΠΙΘ)$/';
|
||||
$exept14 = '/^(ΔΙΑΘ|Θ|ΠΑΡΑΚΑΤΑΘ|ΠΡΟΣΘ|ΣΥΝΘ|)$/';
|
||||
|
||||
if (preg_match($exept13, $token) || preg_match($exept14, $token)) {
|
||||
$token .= "ΗΚ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5h
|
||||
$re = '/^(.+?)(ΟΥΣΑ|ΟΥΣΕΣ|ΟΥΣΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept15 = '/^(ΦΑΡΜΑΚ|ΧΑΔ|ΑΓΚ|ΑΝΑΡΡ|ΒΡΟΜ|ΕΚΛΙΠ|ΛΑΜΠΙΔ|ΛΕΧ|Μ|ΠΑΤ|Ρ|Λ|ΜΕΔ|ΜΕΣΑΖ|ΥΠΟΤΕΙΝ|ΑΜ|ΑΙΘ|ΑΝΗΚ|ΔΕΣΠΟΖ|ΕΝΔΙΑΦΕΡ|ΔΕ|ΔΕΥΤΕΡΕΥ|ΚΑΘΑΡΕΥ|ΠΛΕ|ΤΣΑ)$/';
|
||||
$exept16 = '/(ΠΟΔΑΡ|ΒΛΕΠ|ΠΑΝΤΑΧ|ΦΡΥΔ|ΜΑΝΤΙΛ|ΜΑΛΛ|ΚΥΜΑΤ|ΛΑΧ|ΛΗΓ|ΦΑΓ|ΟΜ|ΠΡΩΤ)$/';
|
||||
|
||||
if (preg_match($exept15, $token) || preg_match($exept16, $token)) {
|
||||
$token .= "ΟΥΣ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5i
|
||||
$re = '/^(.+?)(ΑΓΑ|ΑΓΕΣ|ΑΓΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept17 = '/^(ΨΟΦ|ΝΑΥΛΟΧ)$/';
|
||||
$exept20 = '/(ΚΟΛΛ)$/';
|
||||
$exept18 = '/^(ΑΒΑΣΤ|ΠΟΛΥΦ|ΑΔΗΦ|ΠΑΜΦ|Ρ|ΑΣΠ|ΑΦ|ΑΜΑΛ|ΑΜΑΛΛΙ|ΑΝΥΣΤ|ΑΠΕΡ|ΑΣΠΑΡ|ΑΧΑΡ|ΔΕΡΒΕΝ|ΔΡΟΣΟΠ|ΞΕΦ|ΝΕΟΠ|ΝΟΜΟΤ|ΟΛΟΠ|ΟΜΟΤ|ΠΡΟΣΤ|ΠΡΟΣΩΠΟΠ|'
|
||||
. 'ΣΥΜΠ|ΣΥΝΤ|Τ|ΥΠΟΤ|ΧΑΡ|ΑΕΙΠ|ΑΙΜΟΣΤ|ΑΝΥΠ|ΑΠΟΤ|ΑΡΤΙΠ|ΔΙΑΤ|ΕΝ|ΕΠΙΤ|ΚΡΟΚΑΛΟΠ|ΣΙΔΗΡΟΠ|Λ|ΝΑΥ|ΟΥΛΑΜ|ΟΥΡ|Π|ΤΡ|Μ)$/';
|
||||
$exept19 = '/(ΟΦ|ΠΕΛ|ΧΟΡΤ|ΛΛ|ΣΦ|ΡΠ|ΦΡ|ΠΡ|ΛΟΧ|ΣΜΗΝ)$/';
|
||||
|
||||
if (
|
||||
(preg_match($exept18, $token) || preg_match($exept19, $token))
|
||||
&& !(preg_match($exept17, $token) || preg_match($exept20, $token))
|
||||
) {
|
||||
$token .= "ΑΓ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5j
|
||||
$re = '/^(.+?)(ΗΣΕ|ΗΣΟΥ|ΗΣΑ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept21 = '/^(Ν|ΧΕΡΣΟΝ|ΔΩΔΕΚΑΝ|ΕΡΗΜΟΝ|ΜΕΓΑΛΟΝ|ΕΠΤΑΝ)$/';
|
||||
|
||||
if (preg_match($exept21, $token)) {
|
||||
$token .= "ΗΣ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5k
|
||||
$re = '/^(.+?)(ΗΣΤΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept22 = '/^(ΑΣΒ|ΣΒ|ΑΧΡ|ΧΡ|ΑΠΛ|ΑΕΙΜΝ|ΔΥΣΧΡ|ΕΥΧΡ|ΚΟΙΝΟΧΡ|ΠΑΛΙΜΨ)$/';
|
||||
|
||||
if (preg_match($exept22, $token)) {
|
||||
$token .= "ΗΣΤ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5l
|
||||
$re = '/^(.+?)(ΟΥΝΕ|ΗΣΟΥΝΕ|ΗΘΟΥΝΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept23 = '/^(Ν|Ρ|ΣΠΙ|ΣΤΡΑΒΟΜΟΥΤΣ|ΚΑΚΟΜΟΥΤΣ|ΕΞΩΝ)$/';
|
||||
|
||||
if (preg_match($exept23, $token)) {
|
||||
$token .= "ΟΥΝ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5m
|
||||
$re = '/^(.+?)(ΟΥΜΕ|ΗΣΟΥΜΕ|ΗΘΟΥΜΕ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
$test1 = false;
|
||||
$exept24 = '/^(ΠΑΡΑΣΟΥΣ|Φ|Χ|ΩΡΙΟΠΛ|ΑΖ|ΑΛΛΟΣΟΥΣ|ΑΣΟΥΣ)$/';
|
||||
|
||||
if (preg_match($exept24, $token)) {
|
||||
$token .= "ΟΥΜ";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6
|
||||
$re = '/^(.+?)(ΜΑΤΑ|ΜΑΤΩΝ|ΜΑΤΟΣ)$/';
|
||||
$re2 = '/^(.+?)(Α|ΑΓΑΤΕ|ΑΓΑΝ|ΑΕΙ|ΑΜΑΙ|ΑΝ|ΑΣ|ΑΣΑΙ|ΑΤΑΙ|ΑΩ|Ε|ΕΙ|ΕΙΣ|ΕΙΤΕ|ΕΣΑΙ|ΕΣ|ΕΤΑΙ|Ι|ΙΕΜΑΙ|ΙΕΜΑΣΤΕ|ΙΕΤΑΙ|ΙΕΣΑΙ|ΙΕΣΑΣΤΕ|ΙΟΜΑΣΤΑΝ|ΙΟΜΟΥΝ|'
|
||||
. 'ΙΟΜΟΥΝΑ|ΙΟΝΤΑΝ|ΙΟΝΤΟΥΣΑΝ|ΙΟΣΑΣΤΑΝ|ΙΟΣΑΣΤΕ|ΙΟΣΟΥΝ|ΙΟΣΟΥΝΑ|ΙΟΤΑΝ|ΙΟΥΜΑ|ΙΟΥΜΑΣΤΕ|ΙΟΥΝΤΑΙ|ΙΟΥΝΤΑΝ|Η|ΗΔΕΣ|ΗΔΩΝ|ΗΘΕΙ|ΗΘΕΙΣ|ΗΘΕΙΤΕ|'
|
||||
. 'ΗΘΗΚΑΤΕ|ΗΘΗΚΑΝ|ΗΘΟΥΝ|ΗΘΩ|ΗΚΑΤΕ|ΗΚΑΝ|ΗΣ|ΗΣΑΝ|ΗΣΑΤΕ|ΗΣΕΙ|ΗΣΕΣ|ΗΣΟΥΝ|ΗΣΩ|Ο|ΟΙ|ΟΜΑΙ|ΟΜΑΣΤΑΝ|ΟΜΟΥΝ|ΟΜΟΥΝΑ|ΟΝΤΑΙ|ΟΝΤΑΝ|ΟΝΤΟΥΣΑΝ|ΟΣ|'
|
||||
. 'ΟΣΑΣΤΑΝ|ΟΣΑΣΤΕ|ΟΣΟΥΝ|ΟΣΟΥΝΑ|ΟΤΑΝ|ΟΥ|ΟΥΜΑΙ|ΟΥΜΑΣΤΕ|ΟΥΝ|ΟΥΝΤΑΙ|ΟΥΝΤΑΝ|ΟΥΣ|ΟΥΣΑΝ|ΟΥΣΑΤΕ|Υ|ΥΣ|Ω|ΩΝ)$/';
|
||||
|
||||
if (preg_match($re, $token, $match)) {
|
||||
$token = $match[1] . "ΜΑ";
|
||||
}
|
||||
|
||||
if (preg_match($re2, $token) && $test1) {
|
||||
preg_match($re2, $token, $match);
|
||||
$token = $match[1];
|
||||
}
|
||||
|
||||
// Step 7 (ΠΑΡΑΘΕΤΙΚΑ)
|
||||
$re = '/^(.+?)(ΕΣΤΕΡ|ΕΣΤΑΤ|ΟΤΕΡ|ΟΤΑΤ|ΥΤΕΡ|ΥΤΑΤ|ΩΤΕΡ|ΩΤΑΤ)$/';
|
||||
|
||||
if (preg_match($re, $token)) {
|
||||
preg_match($re, $token, $match);
|
||||
$token = $match[1];
|
||||
}
|
||||
|
||||
return $this->toLowerCase($token, $wCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the token to uppercase, suppressing accents and diaeresis. The array $wCase contains a special map of
|
||||
* the uppercase rule used to convert each character at each position.
|
||||
*
|
||||
* @param string $token Token to process
|
||||
* @param array &$wCase Map of uppercase rules
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function toUpperCase($token, &$wCase)
|
||||
{
|
||||
$wCase = array_fill(0, mb_strlen($token, 'UTF-8'), 0);
|
||||
$caseConvert = [
|
||||
"α" => 'Α',
|
||||
"β" => 'Β',
|
||||
"γ" => 'Γ',
|
||||
"δ" => 'Δ',
|
||||
"ε" => 'Ε',
|
||||
"ζ" => 'Ζ',
|
||||
"η" => 'Η',
|
||||
"θ" => 'Θ',
|
||||
"ι" => 'Ι',
|
||||
"κ" => 'Κ',
|
||||
"λ" => 'Λ',
|
||||
"μ" => 'Μ',
|
||||
"ν" => 'Ν',
|
||||
"ξ" => 'Ξ',
|
||||
"ο" => 'Ο',
|
||||
"π" => 'Π',
|
||||
"ρ" => 'Ρ',
|
||||
"σ" => 'Σ',
|
||||
"τ" => 'Τ',
|
||||
"υ" => 'Υ',
|
||||
"φ" => 'Φ',
|
||||
"χ" => 'Χ',
|
||||
"ψ" => 'Ψ',
|
||||
"ω" => 'Ω',
|
||||
"ά" => 'Α',
|
||||
"έ" => 'Ε',
|
||||
"ή" => 'Η',
|
||||
"ί" => 'Ι',
|
||||
"ό" => 'Ο',
|
||||
"ύ" => 'Υ',
|
||||
"ώ" => 'Ω',
|
||||
"ς" => 'Σ',
|
||||
"ϊ" => 'Ι',
|
||||
"ϋ" => 'Ι',
|
||||
"ΐ" => 'Ι',
|
||||
"ΰ" => 'Υ',
|
||||
];
|
||||
$newToken = '';
|
||||
|
||||
for ($i = 0; $i < mb_strlen($token); $i++) {
|
||||
$char = mb_substr($token, $i, 1);
|
||||
$isLower = \array_key_exists($char, $caseConvert);
|
||||
|
||||
if (!$isLower) {
|
||||
$newToken .= $char;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$upperCase = $caseConvert[$char];
|
||||
$newToken .= $upperCase;
|
||||
|
||||
$wCase[$i] = 1;
|
||||
|
||||
if (\in_array($char, ['ά', 'έ', 'ή', 'ί', 'ό', 'ύ', 'ώ', 'ς'])) {
|
||||
$wCase[$i] = 2;
|
||||
}
|
||||
|
||||
if (\in_array($char, ['ϊ', 'ϋ'])) {
|
||||
$wCase[$i] = 3;
|
||||
}
|
||||
|
||||
if (\in_array($char, ['ΐ', 'ΰ'])) {
|
||||
$wCase[$i] = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return $newToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the suppressed uppercase token back to lowercase, using the $wCase map to add back the accents,
|
||||
* diaeresis and handle the special case of final sigma (different lowercase glyph than the regular sigma, only
|
||||
* used at the end of words).
|
||||
*
|
||||
* @param string $token Token to process
|
||||
* @param array $wCase Map of lowercase rules
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function toLowerCase($token, $wCase)
|
||||
{
|
||||
$newToken = '';
|
||||
|
||||
for ($i = 0; $i < mb_strlen($token); $i++) {
|
||||
$char = mb_substr($token, $i, 1);
|
||||
|
||||
// Is $wCase not set at this position? We assume no case conversion ever took place.
|
||||
if (!isset($wCase[$i])) {
|
||||
$newToken .= $char;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// The character was not case-converted
|
||||
if ($wCase[$i] == 0) {
|
||||
$newToken .= $char;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 1: Unaccented letter
|
||||
if ($wCase[$i] == 1) {
|
||||
$newToken .= mb_strtolower($char);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 2: Vowel with accent (tonos); or the special case of final sigma
|
||||
if ($wCase[$i] == 2) {
|
||||
$charMap = [
|
||||
'Α' => 'ά',
|
||||
'Ε' => 'έ',
|
||||
'Η' => 'ή',
|
||||
'Ι' => 'ί',
|
||||
'Ο' => 'ό',
|
||||
'Υ' => 'ύ',
|
||||
'Ω' => 'ώ',
|
||||
'Σ' => 'ς',
|
||||
];
|
||||
|
||||
$newToken .= $charMap[$char];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 3: vowels with diaeresis (dialytika)
|
||||
if ($wCase[$i] == 3) {
|
||||
$charMap = [
|
||||
'Ι' => 'ϊ',
|
||||
'Υ' => 'ϋ',
|
||||
];
|
||||
|
||||
$newToken .= $charMap[$char];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Case 4: vowels with both diaeresis (dialytika) and accent (tonos)
|
||||
if ($wCase[$i] == 4) {
|
||||
$charMap = [
|
||||
'Ι' => 'ΐ',
|
||||
'Υ' => 'ΰ',
|
||||
];
|
||||
|
||||
$newToken .= $charMap[$char];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// This should never happen!
|
||||
$newToken .= $char;
|
||||
}
|
||||
|
||||
return $newToken;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer\Language;
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Language;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Chinese (simplified) language support class for the Finder indexer package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Zh extends Language
|
||||
{
|
||||
/**
|
||||
* Language locale of the class
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $language = 'zh';
|
||||
|
||||
/**
|
||||
* Spacer between terms
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $spacer = '';
|
||||
|
||||
/**
|
||||
* Method to construct the language object.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($locale = null)
|
||||
{
|
||||
// Override parent constructor since we don't need to load an external stemmer
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to tokenise a text string.
|
||||
*
|
||||
* @param string $input The input to tokenise.
|
||||
*
|
||||
* @return array An array of term strings.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function tokenise($input)
|
||||
{
|
||||
// We first add whitespace around each Chinese character, so that our later code can easily split on this.
|
||||
$input = preg_replace('#\p{Han}#mui', ' $0 ', $input);
|
||||
|
||||
// Now we split up the input into individual terms
|
||||
$terms = parent::tokenise($input);
|
||||
|
||||
return $terms;
|
||||
}
|
||||
}
|
||||
125
administrator/components/com_finder/src/Indexer/Parser.php
Normal file
125
administrator/components/com_finder/src/Indexer/Parser.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Filter\InputFilter;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Parser base class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
abstract class Parser
|
||||
{
|
||||
/**
|
||||
* Parser support instances container.
|
||||
*
|
||||
* @var Parser[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* Method to get a parser, creating it if necessary.
|
||||
*
|
||||
* @param string $format The type of parser to load.
|
||||
*
|
||||
* @return Parser A Parser instance.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on invalid parser.
|
||||
*/
|
||||
public static function getInstance($format)
|
||||
{
|
||||
$format = InputFilter::getInstance()->clean($format, 'cmd');
|
||||
|
||||
// Only create one parser for each format.
|
||||
if (isset(self::$instances[$format])) {
|
||||
return self::$instances[$format];
|
||||
}
|
||||
|
||||
// Setup the adapter for the parser.
|
||||
$class = '\\Joomla\\Component\\Finder\\Administrator\\Indexer\\Parser\\' . ucfirst($format);
|
||||
|
||||
// Check if a parser exists for the format.
|
||||
if (class_exists($class)) {
|
||||
self::$instances[$format] = new $class();
|
||||
|
||||
return self::$instances[$format];
|
||||
}
|
||||
|
||||
// Throw invalid format exception.
|
||||
throw new \Exception(Text::sprintf('COM_FINDER_INDEXER_INVALID_PARSER', $format));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to parse input and extract the plain text. Because this method is
|
||||
* called from both inside and outside the indexer, it needs to be able to
|
||||
* batch out its parsing functionality to deal with the inefficiencies of
|
||||
* regular expressions. We will parse recursively in 2KB chunks.
|
||||
*
|
||||
* @param string $input The input to parse.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function parse($input)
|
||||
{
|
||||
// If the input is less than 2KB we can parse it in one go.
|
||||
if (\strlen($input) <= 2048) {
|
||||
return $this->process($input);
|
||||
}
|
||||
|
||||
// Input is longer than 2Kb so parse it in chunks of 2Kb or less.
|
||||
$start = 0;
|
||||
$end = \strlen($input);
|
||||
$chunk = 2048;
|
||||
$return = null;
|
||||
|
||||
while ($start < $end) {
|
||||
// Setup the string.
|
||||
$string = substr($input, $start, $chunk);
|
||||
|
||||
// Find the last space character if we aren't at the end.
|
||||
$ls = (($start + $chunk) < $end ? strrpos($string, ' ') : false);
|
||||
|
||||
// Truncate to the last space character.
|
||||
if ($ls !== false) {
|
||||
$string = substr($string, 0, $ls);
|
||||
}
|
||||
|
||||
// Adjust the start position for the next iteration.
|
||||
$start += ($ls !== false ? ($ls + 1 - $chunk) + $chunk : $chunk);
|
||||
|
||||
// Parse the chunk.
|
||||
$return .= $this->process($string);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to process input and extract the plain text.
|
||||
*
|
||||
* @param string $input The input to process.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
abstract protected function process($input);
|
||||
}
|
||||
158
administrator/components/com_finder/src/Indexer/Parser/Html.php
Normal file
158
administrator/components/com_finder/src/Indexer/Parser/Html.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* HTML Parser class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Html extends Parser
|
||||
{
|
||||
/**
|
||||
* Method to parse input and extract the plain text. Because this method is
|
||||
* called from both inside and outside the indexer, it needs to be able to
|
||||
* batch out its parsing functionality to deal with the inefficiencies of
|
||||
* regular expressions. We will parse recursively in 2KB chunks.
|
||||
*
|
||||
* @param string $input The input to parse.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function parse($input)
|
||||
{
|
||||
// Strip invalid UTF-8 characters.
|
||||
$oldSetting = ini_get('mbstring.substitute_character');
|
||||
ini_set('mbstring.substitute_character', 'none');
|
||||
$input = mb_convert_encoding($input, 'UTF-8', 'UTF-8');
|
||||
ini_set('mbstring.substitute_character', $oldSetting);
|
||||
|
||||
// Remove anything between <head> and </head> tags. Do this first
|
||||
// because there might be <script> or <style> tags nested inside.
|
||||
$input = $this->removeBlocks($input, '<head>', '</head>');
|
||||
|
||||
// Convert <style> and <noscript> tags to <script> tags
|
||||
// so we can remove them efficiently.
|
||||
$search = [
|
||||
'<style', '</style',
|
||||
'<noscript', '</noscript',
|
||||
];
|
||||
$replace = [
|
||||
'<script', '</script',
|
||||
'<script', '</script',
|
||||
];
|
||||
$input = str_replace($search, $replace, $input);
|
||||
|
||||
// Strip all script blocks.
|
||||
$input = $this->removeBlocks($input, '<script', '</script>');
|
||||
|
||||
// Decode HTML entities.
|
||||
$input = html_entity_decode($input, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
// Convert entities equivalent to spaces to actual spaces.
|
||||
$input = str_replace([' ', ' '], ' ', $input);
|
||||
|
||||
// Add a space before both the OPEN and CLOSE tags of BLOCK and LINE BREAKING elements,
|
||||
// e.g. 'all<h1><em>m</em>obile List</h1>' will become 'all mobile List'
|
||||
$input = preg_replace('/(<|<\/)(' .
|
||||
'address|article|aside|blockquote|br|canvas|dd|div|dl|dt|' .
|
||||
'fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|li|' .
|
||||
'main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video' .
|
||||
')\b/i', ' $1$2', $input);
|
||||
|
||||
// Strip HTML tags.
|
||||
$input = strip_tags($input);
|
||||
|
||||
return parent::parse($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to process HTML input and extract the plain text.
|
||||
*
|
||||
* @param string $input The input to process.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function process($input)
|
||||
{
|
||||
// Replace any amount of white space with a single space.
|
||||
return preg_replace('#\s+#u', ' ', $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove blocks of text between a start and an end tag.
|
||||
* Each block removed is effectively replaced by a single space.
|
||||
*
|
||||
* Note: The start tag and the end tag must be different.
|
||||
* Note: Blocks must not be nested.
|
||||
* Note: This method will function correctly with multi-byte strings.
|
||||
*
|
||||
* @param string $input String to be processed.
|
||||
* @param string $startTag String representing the start tag.
|
||||
* @param string $endTag String representing the end tag.
|
||||
*
|
||||
* @return string with blocks removed.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
private function removeBlocks($input, $startTag, $endTag)
|
||||
{
|
||||
$return = '';
|
||||
$offset = 0;
|
||||
$startTagLength = \strlen($startTag);
|
||||
$endTagLength = \strlen($endTag);
|
||||
|
||||
// Find the first start tag.
|
||||
$start = stripos($input, $startTag);
|
||||
|
||||
// If no start tags were found, return the string unchanged.
|
||||
if ($start === false) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
// Look for all blocks defined by the start and end tags.
|
||||
while ($start !== false) {
|
||||
// Accumulate the substring up to the start tag.
|
||||
$return .= substr($input, $offset, $start - $offset) . ' ';
|
||||
|
||||
// Look for an end tag corresponding to the start tag.
|
||||
$end = stripos($input, $endTag, $start + $startTagLength);
|
||||
|
||||
// If no corresponding end tag, leave the string alone.
|
||||
if ($end === false) {
|
||||
// Fix the offset so part of the string is not duplicated.
|
||||
$offset = $start;
|
||||
break;
|
||||
}
|
||||
|
||||
// Advance the start position.
|
||||
$offset = $end + $endTagLength;
|
||||
|
||||
// Look for the next start tag and loop.
|
||||
$start = stripos($input, $startTag, $offset);
|
||||
}
|
||||
|
||||
// Add in the final substring after the last end tag.
|
||||
$return .= substr($input, $offset);
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* RTF Parser class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Rtf extends Parser
|
||||
{
|
||||
/**
|
||||
* Method to process RTF input and extract the plain text.
|
||||
*
|
||||
* @param string $input The input to process.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function process($input)
|
||||
{
|
||||
// Remove embedded pictures.
|
||||
$input = preg_replace('#{\\\pict[^}]*}#mi', '', $input);
|
||||
|
||||
// Remove control characters.
|
||||
$input = str_replace(['{', '}', "\\\n"], [' ', ' ', "\n"], $input);
|
||||
$input = preg_replace('#\\\([^;]+?);#m', ' ', $input);
|
||||
$input = preg_replace('#\\\[\'a-zA-Z0-9]+#mi', ' ', $input);
|
||||
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Parser;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Text Parser class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Txt extends Parser
|
||||
{
|
||||
/**
|
||||
* Method to process Text input and extract the plain text.
|
||||
*
|
||||
* @param string $input The input to process.
|
||||
*
|
||||
* @return string The plain text input.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function process($input)
|
||||
{
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
1339
administrator/components/com_finder/src/Indexer/Query.php
Normal file
1339
administrator/components/com_finder/src/Indexer/Query.php
Normal file
File diff suppressed because it is too large
Load Diff
582
administrator/components/com_finder/src/Indexer/Result.php
Normal file
582
administrator/components/com_finder/src/Indexer/Result.php
Normal file
@ -0,0 +1,582 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Tree\ImmutableNodeInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Result class for the Finder indexer package.
|
||||
*
|
||||
* This class uses magic __get() and __set() methods to prevent properties
|
||||
* being added that might confuse the system. All properties not explicitly
|
||||
* declared will be pushed into the elements array and can be accessed
|
||||
* explicitly using the getElement() method.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Result implements \Serializable
|
||||
{
|
||||
/**
|
||||
* An array of extra result properties.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $elements = [];
|
||||
|
||||
/**
|
||||
* This array tells the indexer which properties should be indexed and what
|
||||
* weights to use for those properties.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $instructions = [
|
||||
Indexer::TITLE_CONTEXT => ['title', 'subtitle', 'id'],
|
||||
Indexer::TEXT_CONTEXT => ['summary', 'body'],
|
||||
Indexer::META_CONTEXT => ['meta', 'list_price', 'sale_price'],
|
||||
Indexer::PATH_CONTEXT => ['path', 'alias'],
|
||||
Indexer::MISC_CONTEXT => ['comments'],
|
||||
];
|
||||
|
||||
/**
|
||||
* The indexer will use this data to create taxonomy mapping entries for
|
||||
* the item so that it can be filtered by type, label, category,
|
||||
* or whatever.
|
||||
*
|
||||
* @var array
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $taxonomy = [];
|
||||
|
||||
/**
|
||||
* The content URL.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* The content route.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $route;
|
||||
|
||||
/**
|
||||
* The content title.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* The content description.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* The published state of the result.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $published;
|
||||
|
||||
/**
|
||||
* The content published state.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $state;
|
||||
|
||||
/**
|
||||
* The content access level.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $access;
|
||||
|
||||
/**
|
||||
* The content language.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $language = '*';
|
||||
|
||||
/**
|
||||
* The publishing start date.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $publish_start_date;
|
||||
|
||||
/**
|
||||
* The publishing end date.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $publish_end_date;
|
||||
|
||||
/**
|
||||
* The generic start date.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $start_date;
|
||||
|
||||
/**
|
||||
* The generic end date.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $end_date;
|
||||
|
||||
/**
|
||||
* The item list price.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 2.5
|
||||
*/
|
||||
public $list_price;
|
||||
|
||||
/**
|
||||
* The item sale price.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 2.5
|
||||
*/
|
||||
public $sale_price;
|
||||
|
||||
/**
|
||||
* The content type id. This is set by the adapter.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $type_id;
|
||||
|
||||
/**
|
||||
* The default language for content.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public $defaultLanguage;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @since 3.0.3
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->defaultLanguage = ComponentHelper::getParams('com_languages')->get('site', 'en-GB');
|
||||
}
|
||||
|
||||
/**
|
||||
* The magic set method is used to push additional values into the elements
|
||||
* array in order to preserve the cleanliness of the object.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
* @param mixed $value The value of the element.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->setElement($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The magic get method is used to retrieve additional element values from the elements array.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return mixed The value of the element if set, null otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->getElement($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The magic isset method is used to check the state of additional element values in the elements array.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return boolean True if set, false otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return isset($this->elements[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The magic unset method is used to unset additional element values in the elements array.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
unset($this->elements[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve additional element values from the elements array.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
*
|
||||
* @return mixed The value of the element if set, null otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getElement($name)
|
||||
{
|
||||
// Get the element value if set.
|
||||
if (\array_key_exists($name, $this->elements)) {
|
||||
return $this->elements[$name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to retrieve all elements.
|
||||
*
|
||||
* @return array The elements
|
||||
*
|
||||
* @since 3.8.3
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
||||
return $this->elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set additional element values in the elements array.
|
||||
*
|
||||
* @param string $name The name of the element.
|
||||
* @param mixed $value The value of the element.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function setElement($name, $value)
|
||||
{
|
||||
$this->elements[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get all processing instructions.
|
||||
*
|
||||
* @return array An array of processing instructions.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getInstructions()
|
||||
{
|
||||
return $this->instructions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a processing instruction for an item property.
|
||||
*
|
||||
* @param string $group The group to associate the property with.
|
||||
* @param string $property The property to process.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function addInstruction($group, $property)
|
||||
{
|
||||
// Check if the group exists. We can't add instructions for unknown groups.
|
||||
// Check if the property exists in the group.
|
||||
if (\array_key_exists($group, $this->instructions) && !\in_array($property, $this->instructions[$group], true)) {
|
||||
// Add the property to the group.
|
||||
$this->instructions[$group][] = $property;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove a processing instruction for an item property.
|
||||
*
|
||||
* @param string $group The group to associate the property with.
|
||||
* @param string $property The property to process.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function removeInstruction($group, $property)
|
||||
{
|
||||
// Check if the group exists. We can't remove instructions for unknown groups.
|
||||
if (\array_key_exists($group, $this->instructions)) {
|
||||
// Search for the property in the group.
|
||||
$key = array_search($property, $this->instructions[$group]);
|
||||
|
||||
// If the property was found, remove it.
|
||||
if ($key !== false) {
|
||||
unset($this->instructions[$group][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the taxonomy maps for an item.
|
||||
*
|
||||
* @param string $branch The taxonomy branch to get. [optional]
|
||||
*
|
||||
* @return array An array of taxonomy maps.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getTaxonomy($branch = null)
|
||||
{
|
||||
// Get the taxonomy branch if available.
|
||||
if ($branch !== null && isset($this->taxonomy[$branch])) {
|
||||
return $this->taxonomy[$branch];
|
||||
}
|
||||
|
||||
return $this->taxonomy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a taxonomy map for an item.
|
||||
*
|
||||
* @param string $branch The title of the taxonomy branch to add the node to.
|
||||
* @param string $title The title of the taxonomy node.
|
||||
* @param integer $state The published state of the taxonomy node. [optional]
|
||||
* @param integer $access The access level of the taxonomy node. [optional]
|
||||
* @param string $language The language of the taxonomy. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function addTaxonomy($branch, $title, $state = 1, $access = 1, $language = '')
|
||||
{
|
||||
// We can't add taxonomies with empty titles
|
||||
if (!trim($title)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter the input.
|
||||
$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);
|
||||
|
||||
// Create the taxonomy node.
|
||||
$node = new \stdClass();
|
||||
$node->title = $title;
|
||||
$node->state = (int) $state;
|
||||
$node->access = (int) $access;
|
||||
$node->language = $language;
|
||||
$node->nested = false;
|
||||
|
||||
// Add the node to the taxonomy branch.
|
||||
$this->taxonomy[$branch][] = $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a nested taxonomy map for an item.
|
||||
*
|
||||
* @param string $branch The title of the taxonomy branch to add the node to.
|
||||
* @param ImmutableNodeInterface $contentNode The node object.
|
||||
* @param integer $state The published state of the taxonomy node. [optional]
|
||||
* @param integer $access The access level of the taxonomy node. [optional]
|
||||
* @param string $language The language of the taxonomy. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function addNestedTaxonomy($branch, ImmutableNodeInterface $contentNode, $state = 1, $access = 1, $language = '')
|
||||
{
|
||||
// We can't add taxonomies with empty titles
|
||||
if (!trim($contentNode->title)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter the input.
|
||||
$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);
|
||||
|
||||
// Create the taxonomy node.
|
||||
$node = new \stdClass();
|
||||
$node->title = $contentNode->title;
|
||||
$node->state = (int) $state;
|
||||
$node->access = (int) $access;
|
||||
$node->language = $language;
|
||||
$node->nested = true;
|
||||
$node->node = $contentNode;
|
||||
|
||||
// Add the node to the taxonomy branch.
|
||||
$this->taxonomy[$branch][] = $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the item language
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function setLanguage()
|
||||
{
|
||||
if ($this->language == '') {
|
||||
$this->language = $this->defaultLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to serialise the data of a Result object
|
||||
*
|
||||
* @return string The serialised data
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->__serialize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to unserialise the data for this object
|
||||
*
|
||||
* @param string $serialized Serialised data to unserialise
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function unserialize($serialized): void
|
||||
{
|
||||
$this->__unserialize(unserialize($serialized));
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method used for serializing.
|
||||
*
|
||||
* @since 4.1.3
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$taxonomy = [];
|
||||
|
||||
foreach ($this->taxonomy as $branch => $nodes) {
|
||||
$taxonomy[$branch] = [];
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
if ($node->nested) {
|
||||
$n = clone $node;
|
||||
unset($n->node);
|
||||
$taxonomy[$branch][] = $n;
|
||||
} else {
|
||||
$taxonomy[$branch][] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This order must match EXACTLY the order of the $properties in the self::__unserialize method
|
||||
return [
|
||||
$this->access,
|
||||
$this->defaultLanguage,
|
||||
$this->description,
|
||||
$this->elements,
|
||||
$this->end_date,
|
||||
$this->instructions,
|
||||
$this->language,
|
||||
$this->list_price,
|
||||
$this->publish_end_date,
|
||||
$this->publish_start_date,
|
||||
$this->published,
|
||||
$this->route,
|
||||
$this->sale_price,
|
||||
$this->start_date,
|
||||
$this->state,
|
||||
$taxonomy,
|
||||
$this->title,
|
||||
$this->type_id,
|
||||
$this->url,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method used for unserializing.
|
||||
*
|
||||
* @since 4.1.3
|
||||
*/
|
||||
public function __unserialize(array $serialized): void
|
||||
{
|
||||
// This order must match EXACTLY the order of the array in the self::__serialize method
|
||||
$properties = [
|
||||
'access',
|
||||
'defaultLanguage',
|
||||
'description',
|
||||
'elements',
|
||||
'end_date',
|
||||
'instructions',
|
||||
'language',
|
||||
'list_price',
|
||||
'publish_end_date',
|
||||
'publish_start_date',
|
||||
'published',
|
||||
'route',
|
||||
'sale_price',
|
||||
'start_date',
|
||||
'state',
|
||||
'taxonomy',
|
||||
'title',
|
||||
'type_id',
|
||||
'url',
|
||||
];
|
||||
|
||||
foreach ($properties as $k => $v) {
|
||||
$this->$v = $serialized[$k];
|
||||
}
|
||||
|
||||
foreach ($this->taxonomy as $nodes) {
|
||||
foreach ($nodes as $node) {
|
||||
$curTaxonomy = Taxonomy::getTaxonomy($node->id);
|
||||
$node->state = $curTaxonomy->state;
|
||||
$node->access = $curTaxonomy->access;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
514
administrator/components/com_finder/src/Indexer/Taxonomy.php
Normal file
514
administrator/components/com_finder/src/Indexer/Taxonomy.php
Normal file
@ -0,0 +1,514 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Tree\NodeInterface;
|
||||
use Joomla\Component\Finder\Administrator\Table\MapTable;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Taxonomy base class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Taxonomy
|
||||
{
|
||||
/**
|
||||
* An internal cache of taxonomy data.
|
||||
*
|
||||
* @var object[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static $taxonomies = [];
|
||||
|
||||
/**
|
||||
* An internal cache of branch data.
|
||||
*
|
||||
* @var object[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static $branches = [];
|
||||
|
||||
/**
|
||||
* An internal cache of taxonomy node data for inserting it.
|
||||
*
|
||||
* @var object[]
|
||||
* @since 2.5
|
||||
*/
|
||||
public static $nodes = [];
|
||||
|
||||
/**
|
||||
* Method to add a branch to the taxonomy tree.
|
||||
*
|
||||
* @param string $title The title of the branch.
|
||||
* @param integer $state The published state of the branch. [optional]
|
||||
* @param integer $access The access state of the branch. [optional]
|
||||
*
|
||||
* @return integer The id of the branch.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function addBranch($title, $state = 1, $access = 1)
|
||||
{
|
||||
$node = new \stdClass();
|
||||
$node->title = $title;
|
||||
$node->access = $access;
|
||||
$node->parent_id = 1;
|
||||
$node->language = '';
|
||||
|
||||
return self::storeNode($node, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a node to the taxonomy tree.
|
||||
*
|
||||
* @param string $branch The title of the branch to store the node in.
|
||||
* @param string $title The title of the node.
|
||||
* @param integer $state The published state of the node. [optional]
|
||||
* @param integer $access The access state of the node. [optional]
|
||||
* @param string $language The language of the node. [optional]
|
||||
*
|
||||
* @return integer The id of the node.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function addNode($branch, $title, $state = 1, $access = 1, $language = '')
|
||||
{
|
||||
if ($state != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the branch id, insert it if it does not exist.
|
||||
$branchId = static::addBranch($branch);
|
||||
|
||||
$node = new \stdClass();
|
||||
$node->title = $title;
|
||||
$node->access = $access;
|
||||
$node->parent_id = $branchId;
|
||||
$node->language = $language;
|
||||
|
||||
return self::storeNode($node, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a nested node to the taxonomy tree.
|
||||
*
|
||||
* @param string $branch The title of the branch to store the node in.
|
||||
* @param NodeInterface $node The source-node of the taxonomy node.
|
||||
* @param integer $state The published state of the node. [optional]
|
||||
* @param integer $access The access state of the node. [optional]
|
||||
* @param string $language The language of the node. [optional]
|
||||
* @param integer $branchId ID of a branch if known. [optional]
|
||||
*
|
||||
* @return integer The id of the node.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function addNestedNode($branch, NodeInterface $node, $state = 1, $access = 1, $language = '', $branchId = null)
|
||||
{
|
||||
if ($state != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!$branchId) {
|
||||
// Get the branch id, insert it if it does not exist.
|
||||
$branchId = static::addBranch($branch);
|
||||
}
|
||||
|
||||
$parent = $node->getParent();
|
||||
|
||||
$pstate = $node->state ?? ($node->published ?? $state);
|
||||
$paccess = $node->access ?? $access;
|
||||
$planguage = $node->language ?? $language;
|
||||
|
||||
if ($parent && $parent->title != 'ROOT') {
|
||||
$parentId = self::addNestedNode($branch, $parent, $pstate, $paccess, $planguage, $branchId);
|
||||
} else {
|
||||
$parentId = $branchId;
|
||||
}
|
||||
|
||||
if (!$parentId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$temp = new \stdClass();
|
||||
$temp->title = $node->title;
|
||||
$temp->access = $access;
|
||||
$temp->parent_id = $parentId;
|
||||
$temp->language = $language;
|
||||
|
||||
return self::storeNode($temp, $parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method to store a node in the taxonomy
|
||||
*
|
||||
* @param object $node The node data to include
|
||||
* @param integer $parentId The parent id of the node to add.
|
||||
*
|
||||
* @return integer The id of the inserted node.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function storeNode($node, $parentId)
|
||||
{
|
||||
// Check to see if the node is in the cache.
|
||||
if (isset(static::$nodes[$parentId . ':' . $node->title])) {
|
||||
return static::$nodes[$parentId . ':' . $node->title]->id;
|
||||
}
|
||||
|
||||
// Check to see if the node is in the table.
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' = ' . $db->quote($parentId))
|
||||
->where($db->quoteName('title') . ' = ' . $db->quote($node->title))
|
||||
->where($db->quoteName('language') . ' = ' . $db->quote($node->language));
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
// Get the result.
|
||||
$result = $db->loadObject();
|
||||
|
||||
// Check if the database matches the input data.
|
||||
if ((bool) $result && $result->access == $node->access) {
|
||||
// The data matches, add the item to the cache.
|
||||
static::$nodes[$parentId . ':' . $node->title] = $result;
|
||||
|
||||
return static::$nodes[$parentId . ':' . $node->title]->id;
|
||||
}
|
||||
|
||||
/*
|
||||
* The database did not match the input. This could be because the
|
||||
* state has changed or because the node does not exist. Let's figure
|
||||
* out which case is true and deal with it.
|
||||
* @todo: use factory?
|
||||
*/
|
||||
$nodeTable = new MapTable($db);
|
||||
|
||||
if (empty($result)) {
|
||||
// Prepare the node object.
|
||||
$nodeTable->title = $node->title;
|
||||
$nodeTable->access = (int) $node->access;
|
||||
$nodeTable->language = $node->language;
|
||||
$nodeTable->setLocation((int) $parentId, 'last-child');
|
||||
} else {
|
||||
// Prepare the node object.
|
||||
$nodeTable->id = (int) $result->id;
|
||||
$nodeTable->title = $result->title;
|
||||
$nodeTable->access = (int) $result->access;
|
||||
$nodeTable->language = $node->language;
|
||||
$nodeTable->setLocation($result->parent_id, 'last-child');
|
||||
}
|
||||
|
||||
// Check the data.
|
||||
if (!$nodeTable->check()) {
|
||||
$error = $nodeTable->getError();
|
||||
|
||||
if ($error instanceof \Exception) {
|
||||
// \Joomla\CMS\Table\NestedTable sets errors of exceptions, so in this case we can pass on more
|
||||
// information
|
||||
throw new \RuntimeException(
|
||||
$error->getMessage(),
|
||||
$error->getCode(),
|
||||
$error
|
||||
);
|
||||
}
|
||||
|
||||
// Standard string returned. Probably from the \Joomla\CMS\Table\Table class
|
||||
throw new \RuntimeException($error, 500);
|
||||
}
|
||||
|
||||
// Store the data.
|
||||
if (!$nodeTable->store()) {
|
||||
$error = $nodeTable->getError();
|
||||
|
||||
if ($error instanceof \Exception) {
|
||||
// \Joomla\CMS\Table\NestedTable sets errors of exceptions, so in this case we can pass on more
|
||||
// information
|
||||
throw new \RuntimeException(
|
||||
$error->getMessage(),
|
||||
$error->getCode(),
|
||||
$error
|
||||
);
|
||||
}
|
||||
|
||||
// Standard string returned. Probably from the \Joomla\CMS\Table\Table class
|
||||
throw new \RuntimeException($error, 500);
|
||||
}
|
||||
|
||||
$nodeTable->rebuildPath($nodeTable->id);
|
||||
|
||||
// Add the node to the cache.
|
||||
static::$nodes[$parentId . ':' . $nodeTable->title] = (object) $nodeTable->getProperties();
|
||||
|
||||
return static::$nodes[$parentId . ':' . $nodeTable->title]->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a map entry between a link and a taxonomy node.
|
||||
*
|
||||
* @param integer $linkId The link to map to.
|
||||
* @param integer $nodeId The node to map to.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function addMap($linkId, $nodeId)
|
||||
{
|
||||
// Insert the map.
|
||||
$db = Factory::getDbo();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('link_id'))
|
||||
->from($db->quoteName('#__finder_taxonomy_map'))
|
||||
->where($db->quoteName('link_id') . ' = ' . (int) $linkId)
|
||||
->where($db->quoteName('node_id') . ' = ' . (int) $nodeId);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
$id = (int) $db->loadResult();
|
||||
|
||||
if (!$id) {
|
||||
$map = new \stdClass();
|
||||
$map->link_id = (int) $linkId;
|
||||
$map->node_id = (int) $nodeId;
|
||||
$db->insertObject('#__finder_taxonomy_map', $map);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the title of all taxonomy branches.
|
||||
*
|
||||
* @return array An array of branch titles.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function getBranchTitles()
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Set user variables
|
||||
$groups = implode(',', Factory::getUser()->getAuthorisedViewLevels());
|
||||
|
||||
// Create a query to get the taxonomy branch titles.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('title'))
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' = 1')
|
||||
->where($db->quoteName('state') . ' = 1')
|
||||
->where($db->quoteName('access') . ' IN (' . $groups . ')');
|
||||
|
||||
// Get the branch titles.
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to find a taxonomy node in a branch.
|
||||
*
|
||||
* @param string $branch The branch to search.
|
||||
* @param string $title The title of the node.
|
||||
*
|
||||
* @return mixed Integer id on success, null on no match.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function getNodeByTitle($branch, $title)
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// Set user variables
|
||||
$groups = implode(',', Factory::getUser()->getAuthorisedViewLevels());
|
||||
|
||||
// Create a query to get the node.
|
||||
$query = $db->getQuery(true)
|
||||
->select('t1.*')
|
||||
->from($db->quoteName('#__finder_taxonomy') . ' AS t1')
|
||||
->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id')
|
||||
->where('t1.access IN (' . $groups . ')')
|
||||
->where('t1.state = 1')
|
||||
->where('t1.title LIKE ' . $db->quote($db->escape($title) . '%'))
|
||||
->where('t2.access IN (' . $groups . ')')
|
||||
->where('t2.state = 1')
|
||||
->where('t2.title = ' . $db->quote($branch));
|
||||
|
||||
// Get the node.
|
||||
$query->setLimit(1);
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove map entries for a link.
|
||||
*
|
||||
* @param integer $linkId The link to remove.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function removeMaps($linkId)
|
||||
{
|
||||
// Delete the maps.
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__finder_taxonomy_map'))
|
||||
->where($db->quoteName('link_id') . ' = ' . (int) $linkId);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove orphaned taxonomy maps
|
||||
*
|
||||
* @return integer The number of deleted rows.
|
||||
*
|
||||
* @since 4.2.0
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function removeOrphanMaps()
|
||||
{
|
||||
// Delete all orphaned maps
|
||||
$db = Factory::getDbo();
|
||||
$query2 = $db->getQuery(true)
|
||||
->select($db->quoteName('link_id'))
|
||||
->from($db->quoteName('#__finder_links'));
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__finder_taxonomy_map'))
|
||||
->where($db->quoteName('link_id') . ' NOT IN (' . $query2 . ')');
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
$count = $db->getAffectedRows();
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove orphaned taxonomy nodes and branches.
|
||||
*
|
||||
* @return integer The number of deleted rows.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \RuntimeException on database error.
|
||||
*/
|
||||
public static function removeOrphanNodes()
|
||||
{
|
||||
// Delete all orphaned nodes.
|
||||
$affectedRows = 0;
|
||||
$db = Factory::getDbo();
|
||||
$nodeTable = new MapTable($db);
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select($db->quoteName('t.id'))
|
||||
->from($db->quoteName('#__finder_taxonomy', 't'))
|
||||
->join('LEFT', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.node_id') . '=' . $db->quoteName('t.id'))
|
||||
->where($db->quoteName('t.parent_id') . ' > 1 ')
|
||||
->where('t.lft + 1 = t.rgt')
|
||||
->where($db->quoteName('m.link_id') . ' IS NULL');
|
||||
|
||||
do {
|
||||
$db->setQuery($query);
|
||||
$nodes = $db->loadColumn();
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$nodeTable->delete($node);
|
||||
$affectedRows++;
|
||||
}
|
||||
} while ($nodes);
|
||||
|
||||
return $affectedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a taxonomy based on its id or all taxonomies
|
||||
*
|
||||
* @param integer $id Id of the taxonomy
|
||||
*
|
||||
* @return object|object[] A taxonomy object or an array of all taxonomies
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getTaxonomy($id = 0)
|
||||
{
|
||||
if (!\count(self::$taxonomies)) {
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select(['id','parent_id','lft','rgt','level','path','title','alias','state','access','language'])
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->order($db->quoteName('lft'));
|
||||
|
||||
$db->setQuery($query);
|
||||
self::$taxonomies = $db->loadObjectList('id');
|
||||
}
|
||||
|
||||
if ($id == 0) {
|
||||
return self::$taxonomies;
|
||||
}
|
||||
|
||||
if (isset(self::$taxonomies[$id])) {
|
||||
return self::$taxonomies[$id];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a taxonomy branch object based on its title or all branches
|
||||
*
|
||||
* @param string $title Title of the branch
|
||||
*
|
||||
* @return object|object[] The object with the branch data or an array of all branches
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getBranch($title = '')
|
||||
{
|
||||
if (!\count(self::$branches)) {
|
||||
$taxonomies = self::getTaxonomy();
|
||||
|
||||
foreach ($taxonomies as $t) {
|
||||
if ($t->level == 1) {
|
||||
self::$branches[$t->title] = $t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($title == '') {
|
||||
return self::$branches;
|
||||
}
|
||||
|
||||
if (isset(self::$branches[$title])) {
|
||||
return self::$branches[$title];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
185
administrator/components/com_finder/src/Indexer/Token.php
Normal file
185
administrator/components/com_finder/src/Indexer/Token.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Indexer;
|
||||
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Token class for the Finder indexer package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Token
|
||||
{
|
||||
/**
|
||||
* This is the term that will be referenced in the terms table and the
|
||||
* mapping tables.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $term;
|
||||
|
||||
/**
|
||||
* The stem is used to match the root term and produce more potential
|
||||
* matches when searching the index.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $stem;
|
||||
|
||||
/**
|
||||
* If the token is numeric, it is likely to be short and uncommon so the
|
||||
* weight is adjusted to compensate for that situation.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.5
|
||||
*/
|
||||
public $numeric;
|
||||
|
||||
/**
|
||||
* If the token is a common term, the weight is adjusted to compensate for
|
||||
* the higher frequency of the term in relation to other terms.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.5
|
||||
*/
|
||||
public $common;
|
||||
|
||||
/**
|
||||
* Flag for phrase tokens.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 2.5
|
||||
*/
|
||||
public $phrase;
|
||||
|
||||
/**
|
||||
* The length is used to calculate the weight of the token.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $length;
|
||||
|
||||
/**
|
||||
* The weight is calculated based on token size and whether the token is
|
||||
* considered a common term.
|
||||
*
|
||||
* @var integer
|
||||
* @since 2.5
|
||||
*/
|
||||
public $weight;
|
||||
|
||||
/**
|
||||
* The simple language identifier for the token.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
public $language;
|
||||
|
||||
/**
|
||||
* The container for matches.
|
||||
*
|
||||
* @var array
|
||||
* @since 3.8.12
|
||||
*/
|
||||
public $matches = [];
|
||||
|
||||
/**
|
||||
* Is derived token (from individual words)
|
||||
*
|
||||
* @var boolean
|
||||
* @since 3.8.12
|
||||
*/
|
||||
public $derived;
|
||||
|
||||
/**
|
||||
* The suggested term
|
||||
*
|
||||
* @var string
|
||||
* @since 3.8.12
|
||||
*/
|
||||
public $suggestion;
|
||||
|
||||
/**
|
||||
* The token required flag
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $required;
|
||||
|
||||
/**
|
||||
* Method to construct the token object.
|
||||
*
|
||||
* @param mixed $term The term as a string for words or an array for phrases.
|
||||
* @param string $lang The simple language identifier.
|
||||
* @param string $spacer The space separator for phrases. [optional]
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct($term, $lang, $spacer = ' ')
|
||||
{
|
||||
if (!$lang) {
|
||||
$this->language = '*';
|
||||
} else {
|
||||
$this->language = $lang;
|
||||
}
|
||||
|
||||
// Tokens can be a single word or an array of words representing a phrase.
|
||||
if (\is_array($term)) {
|
||||
// Populate the token instance.
|
||||
$this->term = implode($spacer, $term);
|
||||
$this->stem = implode($spacer, array_map([Helper::class, 'stem'], $term, [$lang]));
|
||||
$this->numeric = false;
|
||||
$this->common = false;
|
||||
$this->phrase = true;
|
||||
$this->length = StringHelper::strlen($this->term);
|
||||
|
||||
/*
|
||||
* Calculate the weight of the token.
|
||||
*
|
||||
* 1. Length of the token up to 30 and divide by 30, add 1.
|
||||
* 2. Round weight to 4 decimal points.
|
||||
*/
|
||||
$this->weight = (min($this->length, 30) / 30) + 1;
|
||||
$this->weight = round($this->weight, 4);
|
||||
} else {
|
||||
// Populate the token instance.
|
||||
$this->term = $term;
|
||||
$this->stem = Helper::stem($this->term, $lang);
|
||||
$this->numeric = (is_numeric($this->term) || (bool) preg_match('#^[0-9,.\-\+]+$#', $this->term));
|
||||
$this->common = $this->numeric ? false : Helper::isCommon($this->term, $lang);
|
||||
$this->phrase = false;
|
||||
$this->length = StringHelper::strlen($this->term);
|
||||
|
||||
/*
|
||||
* Calculate the weight of the token.
|
||||
*
|
||||
* 1. Length of the token up to 15 and divide by 15.
|
||||
* 2. If common term, divide weight by 8.
|
||||
* 3. If numeric, multiply weight by 1.5.
|
||||
* 4. Round weight to 4 decimal points.
|
||||
*/
|
||||
$this->weight = min($this->length, 15) / 15;
|
||||
$this->weight = $this->common === true ? $this->weight / 8 : $this->weight;
|
||||
$this->weight = $this->numeric === true ? $this->weight * 1.5 : $this->weight;
|
||||
$this->weight = round($this->weight, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
154
administrator/components/com_finder/src/Model/FilterModel.php
Normal file
154
administrator/components/com_finder/src/Model/FilterModel.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\Component\Finder\Administrator\Table\FilterTable;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filter model class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FilterModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $text_prefix = 'COM_FINDER';
|
||||
|
||||
/**
|
||||
* Model context string.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $context = 'com_finder.filter';
|
||||
|
||||
/**
|
||||
* Custom clean cache method.
|
||||
*
|
||||
* @param string $group The component name. [optional]
|
||||
* @param integer $clientId No longer used, will be removed without replacement
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function cleanCache($group = 'com_finder', $clientId = 0)
|
||||
{
|
||||
parent::cleanCache($group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the filter data.
|
||||
*
|
||||
* @return FilterTable|boolean The filter data or false on a failure.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getFilter()
|
||||
{
|
||||
$filter_id = (int) $this->getState('filter.id');
|
||||
|
||||
// Get a FinderTableFilter instance.
|
||||
$filter = $this->getTable();
|
||||
|
||||
// Attempt to load the row.
|
||||
$return = $filter->load($filter_id);
|
||||
|
||||
// Check for a database error.
|
||||
if ($return === false && $filter->getError()) {
|
||||
$this->setError($filter->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process the filter data.
|
||||
if (!empty($filter->data)) {
|
||||
$filter->data = explode(',', $filter->data);
|
||||
} elseif (empty($filter->data)) {
|
||||
$filter->data = [];
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the record form.
|
||||
*
|
||||
* @param array $data Data for the form. [optional]
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not. [optional]
|
||||
*
|
||||
* @return Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_finder.filter', 'filter', ['control' => 'jform', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = Factory::getApplication()->getUserState('com_finder.edit.filter.data', []);
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getItem();
|
||||
}
|
||||
|
||||
$this->preprocessData('com_finder.filter', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the total indexed items
|
||||
*
|
||||
* @return integer The count of indexed items
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getTotal()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('MAX(link_id)')
|
||||
->from('#__finder_links');
|
||||
|
||||
return $db->setQuery($query)->loadResult();
|
||||
}
|
||||
}
|
||||
141
administrator/components/com_finder/src/Model/FiltersModel.php
Normal file
141
administrator/components/com_finder/src/Model/FiltersModel.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filters model class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FiltersModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 3.7
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'filter_id', 'a.filter_id',
|
||||
'title', 'a.title',
|
||||
'state', 'a.state',
|
||||
'created_by_alias', 'a.created_by_alias',
|
||||
'created', 'a.created',
|
||||
'map_count', 'a.map_count',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return \Joomla\Database\DatabaseQuery
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// Select all fields from the table.
|
||||
$query->select('a.*')
|
||||
->from($db->quoteName('#__finder_filters', 'a'));
|
||||
|
||||
// Join over the users for the checked out user.
|
||||
$query->select($db->quoteName('uc.name', 'editor'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'uc') . ' ON ' . $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out'));
|
||||
|
||||
// Join over the users for the author.
|
||||
$query->select($db->quoteName('ua.name', 'user_name'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'ua') . ' ON ' . $db->quoteName('ua.id') . ' = ' . $db->quoteName('a.created_by'));
|
||||
|
||||
// Check for a search filter.
|
||||
if ($search = $this->getState('filter.search')) {
|
||||
$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
|
||||
$query->where($db->quoteName('a.title') . ' LIKE ' . $search);
|
||||
}
|
||||
|
||||
// If the model is set to check item state, add to the query.
|
||||
$state = $this->getState('filter.state');
|
||||
|
||||
if (is_numeric($state)) {
|
||||
$query->where($db->quoteName('a.state') . ' = ' . (int) $state);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$query->order($db->escape($this->getState('list.ordering', 'a.title') . ' ' . $db->escape($this->getState('list.direction', 'ASC'))));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* This is necessary because the model is used by the component and
|
||||
* different modules that might need different sets of data or different
|
||||
* ordering requirements.
|
||||
*
|
||||
* @param string $id A prefix for the store id. [optional]
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
$id .= ':' . $this->getState('filter.state');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field. [optional]
|
||||
* @param string $direction An optional direction. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function populateState($ordering = 'a.title', $direction = 'asc')
|
||||
{
|
||||
// Load the filter state.
|
||||
$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
|
||||
$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
|
||||
|
||||
// Load the parameters.
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$this->setState('params', $params);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
}
|
||||
466
administrator/components/com_finder/src/Model/IndexModel.php
Normal file
466
administrator/components/com_finder/src/Model/IndexModel.php
Normal file
@ -0,0 +1,466 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Index model class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class IndexModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* The event to trigger after deleting the data.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $event_after_delete = 'onContentAfterDelete';
|
||||
|
||||
/**
|
||||
* The event to trigger before deleting the data.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.5
|
||||
*/
|
||||
protected $event_before_delete = 'onContentBeforeDelete';
|
||||
|
||||
/**
|
||||
* The event to trigger after purging the data.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $event_after_purge = 'onFinderIndexAfterPurge';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 3.7
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'state', 'published', 'l.published',
|
||||
'title', 'l.title',
|
||||
'type', 'type_id', 'l.type_id',
|
||||
't.title', 't_title',
|
||||
'url', 'l.url',
|
||||
'language', 'l.language',
|
||||
'indexdate', 'l.indexdate',
|
||||
'content_map',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can be deleted.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to delete the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function canDelete($record)
|
||||
{
|
||||
return $this->getCurrentUser()->authorise('core.delete', $this->option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can have its state changed.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to change the state of the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function canEditState($record)
|
||||
{
|
||||
return $this->getCurrentUser()->authorise('core.edit.state', $this->option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delete one or more records.
|
||||
*
|
||||
* @param array $pks An array of record primary keys.
|
||||
*
|
||||
* @return boolean True if successful, false if an error occurs.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function delete(&$pks)
|
||||
{
|
||||
$pks = (array) $pks;
|
||||
$table = $this->getTable();
|
||||
|
||||
// Include the content plugins for the on delete events.
|
||||
PluginHelper::importPlugin('content');
|
||||
|
||||
// Iterate the items to delete each one.
|
||||
foreach ($pks as $i => $pk) {
|
||||
if ($table->load($pk)) {
|
||||
if ($this->canDelete($table)) {
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
// Trigger the onContentBeforeDelete event.
|
||||
$result = Factory::getApplication()->triggerEvent($this->event_before_delete, [$context, $table]);
|
||||
|
||||
if (\in_array(false, $result, true)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$table->delete($pk)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trigger the onContentAfterDelete event.
|
||||
Factory::getApplication()->triggerEvent($this->event_after_delete, [$context, $table]);
|
||||
} else {
|
||||
// Prune items that you can't change.
|
||||
unset($pks[$i]);
|
||||
$error = $this->getError();
|
||||
|
||||
if ($error) {
|
||||
$this->setError($error);
|
||||
} else {
|
||||
$this->setError(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the component's cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return \Joomla\Database\DatabaseQuery
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('l.*')
|
||||
->select($db->quoteName('t.title', 't_title'))
|
||||
->from($db->quoteName('#__finder_links', 'l'))
|
||||
->join('INNER', $db->quoteName('#__finder_types', 't') . ' ON ' . $db->quoteName('t.id') . ' = ' . $db->quoteName('l.type_id'));
|
||||
|
||||
// Check the type filter.
|
||||
$type = $this->getState('filter.type');
|
||||
|
||||
// Join over the language
|
||||
$query->select('la.title AS language_title, la.image AS language_image')
|
||||
->join('LEFT', $db->quoteName('#__languages') . ' AS la ON la.lang_code = l.language');
|
||||
|
||||
if (is_numeric($type)) {
|
||||
$query->where($db->quoteName('l.type_id') . ' = ' . (int) $type);
|
||||
}
|
||||
|
||||
// Check the map filter.
|
||||
$contentMapId = $this->getState('filter.content_map');
|
||||
|
||||
if (is_numeric($contentMapId)) {
|
||||
$query->join('INNER', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.link_id') . ' = ' . $db->quoteName('l.link_id'))
|
||||
->where($db->quoteName('m.node_id') . ' = ' . (int) $contentMapId);
|
||||
}
|
||||
|
||||
// Check for state filter.
|
||||
$state = $this->getState('filter.state');
|
||||
|
||||
if (is_numeric($state)) {
|
||||
$query->where($db->quoteName('l.published') . ' = ' . (int) $state);
|
||||
}
|
||||
|
||||
// Filter on the language.
|
||||
if ($language = $this->getState('filter.language')) {
|
||||
$query->where($db->quoteName('l.language') . ' = ' . $db->quote($language));
|
||||
}
|
||||
|
||||
// Check the search phrase.
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
|
||||
$orSearchSql = $db->quoteName('l.title') . ' LIKE ' . $search . ' OR ' . $db->quoteName('l.url') . ' LIKE ' . $search;
|
||||
|
||||
// Filter by indexdate only if $search doesn't contains non-ascii characters
|
||||
if (!preg_match('/[^\x00-\x7F]/', $search)) {
|
||||
$orSearchSql .= ' OR ' . $query->castAsChar($db->quoteName('l.indexdate')) . ' LIKE ' . $search;
|
||||
}
|
||||
|
||||
$query->where('(' . $orSearchSql . ')');
|
||||
}
|
||||
|
||||
// Handle the list ordering.
|
||||
$listOrder = $this->getState('list.ordering', 'l.title');
|
||||
$listDir = $this->getState('list.direction', 'ASC');
|
||||
|
||||
if ($listOrder === 't.title') {
|
||||
$ordering = $db->quoteName('t.title') . ' ' . $db->escape($listDir) . ', ' . $db->quoteName('l.title') . ' ' . $db->escape($listDir);
|
||||
} else {
|
||||
$ordering = $db->escape($listOrder) . ' ' . $db->escape($listDir);
|
||||
}
|
||||
|
||||
$query->order($ordering);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the state of the Smart Search Plugins.
|
||||
*
|
||||
* @return array Array of relevant plugins and whether they are enabled or not.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getPluginState()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('name, enabled')
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
|
||||
->where($db->quoteName('folder') . ' IN (' . $db->quote('system') . ',' . $db->quote('content') . ')')
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('finder'));
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObjectList('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* This is necessary because the model is used by the component and
|
||||
* different modules that might need different sets of data or different
|
||||
* ordering requirements.
|
||||
*
|
||||
* @param string $id A prefix for the store id. [optional]
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
$id .= ':' . $this->getState('filter.state');
|
||||
$id .= ':' . $this->getState('filter.type');
|
||||
$id .= ':' . $this->getState('filter.content_map');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total of indexed items.
|
||||
*
|
||||
* @return integer The total of indexed items.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function getTotalIndexed()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('COUNT(link_id)')
|
||||
->from($db->quoteName('#__finder_links'));
|
||||
$db->setQuery($query);
|
||||
|
||||
return (int) $db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Table object, always creating it.
|
||||
*
|
||||
* @param string $type The table type to instantiate. [optional]
|
||||
* @param string $prefix A prefix for the table class name. [optional]
|
||||
* @param array $config Configuration array for model. [optional]
|
||||
*
|
||||
* @return \Joomla\CMS\Table\Table A database object
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getTable($type = 'Link', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getTable($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to purge the index, deleting all links.
|
||||
*
|
||||
* @return boolean True on success, false on failure.
|
||||
*
|
||||
* @since 2.5
|
||||
* @throws \Exception on database error
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Truncate the links table.
|
||||
$db->truncateTable('#__finder_links');
|
||||
|
||||
// Truncate the links terms tables.
|
||||
$db->truncateTable('#__finder_links_terms');
|
||||
|
||||
// Truncate the terms table.
|
||||
$db->truncateTable('#__finder_terms');
|
||||
|
||||
// Truncate the taxonomy map table.
|
||||
$db->truncateTable('#__finder_taxonomy_map');
|
||||
|
||||
// Truncate the taxonomy table and insert the root node.
|
||||
$db->truncateTable('#__finder_taxonomy');
|
||||
$root = (object) [
|
||||
'id' => 1,
|
||||
'parent_id' => 0,
|
||||
'lft' => 0,
|
||||
'rgt' => 1,
|
||||
'level' => 0,
|
||||
'path' => '',
|
||||
'title' => 'ROOT',
|
||||
'alias' => 'root',
|
||||
'state' => 1,
|
||||
'access' => 1,
|
||||
'language' => '*',
|
||||
];
|
||||
$db->insertObject('#__finder_taxonomy', $root);
|
||||
|
||||
// Truncate the tokens tables.
|
||||
$db->truncateTable('#__finder_tokens');
|
||||
|
||||
// Truncate the tokens aggregate table.
|
||||
$db->truncateTable('#__finder_tokens_aggregate');
|
||||
|
||||
// Include the finder plugins for the on purge events.
|
||||
PluginHelper::importPlugin('finder');
|
||||
Factory::getApplication()->triggerEvent($this->event_after_purge);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field. [optional]
|
||||
* @param string $direction An optional direction. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function populateState($ordering = 'l.title', $direction = 'asc')
|
||||
{
|
||||
// Load the filter state.
|
||||
$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
|
||||
$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
|
||||
$this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'cmd'));
|
||||
$this->setState('filter.content_map', $this->getUserStateFromRequest($this->context . '.filter.content_map', 'filter_content_map', '', 'cmd'));
|
||||
$this->setState('filter.language', $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', ''));
|
||||
|
||||
// Load the parameters.
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$this->setState('params', $params);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the published state of one or more records.
|
||||
*
|
||||
* @param array $pks A list of the primary keys to change.
|
||||
* @param integer $value The value of the published state. [optional]
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function publish(&$pks, $value = 1)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$table = $this->getTable();
|
||||
$pks = (array) $pks;
|
||||
|
||||
// Include the content plugins for the change of state event.
|
||||
PluginHelper::importPlugin('content');
|
||||
|
||||
// Access checks.
|
||||
foreach ($pks as $i => $pk) {
|
||||
$table->reset();
|
||||
|
||||
if ($table->load($pk) && !$this->canEditState($table)) {
|
||||
// Prune items that you can't change.
|
||||
unset($pks[$i]);
|
||||
$this->setError(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to change the state of the records.
|
||||
if (!$table->publish($pks, $value, $user->get('id'))) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
// Trigger the onContentChangeState event.
|
||||
$result = Factory::getApplication()->triggerEvent('onContentChangeState', [$context, $pks, $value]);
|
||||
|
||||
if (\in_array(false, $result, true)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the component's cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\MVC\Model\FormModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Indexer model class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class IndexerModel extends FormModel
|
||||
{
|
||||
/**
|
||||
* Method for getting a form.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_finder.indexer', 'indexer', ['control' => '', 'load_data' => $loadData]);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
107
administrator/components/com_finder/src/Model/ItemModel.php
Normal file
107
administrator/components/com_finder/src/Model/ItemModel.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
/**
|
||||
* Index Item model class for Finder.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class ItemModel extends BaseDatabaseModel
|
||||
{
|
||||
/**
|
||||
* Stock method to auto-populate the model state.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
// Get the pk of the record from the request.
|
||||
$pk = Factory::getApplication()->getInput()->getInt('id');
|
||||
$this->setState('item.link_id', $pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a finder link object
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function getItem()
|
||||
{
|
||||
$link_id = (int) $this->getState('item.link_id');
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__finder_links', 'l'))
|
||||
->where($db->quoteName('l.link_id') . ' = :link_id')
|
||||
->bind(':link_id', $link_id, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get terms associated with a finder link
|
||||
*
|
||||
* @return object[]
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function getTerms()
|
||||
{
|
||||
$link_id = (int) $this->getState('item.link_id');
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('t.*, l.*')
|
||||
->from($db->quoteName('#__finder_links_terms', 'l'))
|
||||
->leftJoin($db->quoteName('#__finder_terms', 't') . ' ON ' . $db->quoteName('t.term_id') . ' = ' . $db->quoteName('l.term_id'))
|
||||
->where($db->quoteName('l.link_id') . ' = :link_id')
|
||||
->order('l.weight')
|
||||
->bind(':link_id', $link_id, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObjectList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxonomies associated with a finder link
|
||||
*
|
||||
* @return \stdClass[]
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function getTaxonomies()
|
||||
{
|
||||
$link_id = (int) $this->getState('item.link_id');
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('t.*, m.*')
|
||||
->from($db->quoteName('#__finder_taxonomy_map', 'm'))
|
||||
->leftJoin($db->quoteName('#__finder_taxonomy', 't') . ' ON ' . $db->quoteName('t.id') . ' = ' . $db->quoteName('m.node_id'))
|
||||
->where($db->quoteName('m.link_id') . ' = :link_id')
|
||||
->order('t.title')
|
||||
->bind(':link_id', $link_id, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObjectList();
|
||||
}
|
||||
}
|
||||
403
administrator/components/com_finder/src/Model/MapsModel.php
Normal file
403
administrator/components/com_finder/src/Model/MapsModel.php
Normal file
@ -0,0 +1,403 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Maps model for the Finder package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class MapsModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 3.7
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'state', 'a.state',
|
||||
'title', 'a.title',
|
||||
'branch',
|
||||
'branch_title', 'd.branch_title',
|
||||
'level', 'd.level',
|
||||
'language', 'a.language',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can be deleted.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to delete the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function canDelete($record)
|
||||
{
|
||||
return $this->getCurrentUser()->authorise('core.delete', $this->option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can have its state changed.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to change the state of the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function canEditState($record)
|
||||
{
|
||||
return $this->getCurrentUser()->authorise('core.edit.state', $this->option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delete one or more records.
|
||||
*
|
||||
* @param array $pks An array of record primary keys.
|
||||
*
|
||||
* @return boolean True if successful, false if an error occurs.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function delete(&$pks)
|
||||
{
|
||||
$pks = (array) $pks;
|
||||
$table = $this->getTable();
|
||||
|
||||
// Include the content plugins for the on delete events.
|
||||
PluginHelper::importPlugin('content');
|
||||
|
||||
// Iterate the items to check if all of them exist.
|
||||
foreach ($pks as $i => $pk) {
|
||||
if (!$table->load($pk)) {
|
||||
// Item is not in the table.
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate the items to delete each one.
|
||||
foreach ($pks as $i => $pk) {
|
||||
if ($table->load($pk)) {
|
||||
if ($this->canDelete($table)) {
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
// Trigger the onContentBeforeDelete event.
|
||||
$result = Factory::getApplication()->triggerEvent('onContentBeforeDelete', [$context, $table]);
|
||||
|
||||
if (\in_array(false, $result, true)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$table->delete($pk)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trigger the onContentAfterDelete event.
|
||||
Factory::getApplication()->triggerEvent('onContentAfterDelete', [$context, $table]);
|
||||
} else {
|
||||
// Prune items that you can't change.
|
||||
unset($pks[$i]);
|
||||
$error = $this->getError();
|
||||
|
||||
if ($error) {
|
||||
$this->setError($error);
|
||||
} else {
|
||||
$this->setError(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the component's cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return \Joomla\Database\DatabaseQuery
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Select all fields from the table.
|
||||
$query = $db->getQuery(true)
|
||||
->select('a.id, a.parent_id, a.lft, a.rgt, a.level, a.path, a.title, a.alias, a.state, a.access, a.language')
|
||||
->from($db->quoteName('#__finder_taxonomy', 'a'))
|
||||
->where('a.parent_id != 0');
|
||||
|
||||
// Join to get the branch title
|
||||
$query->select([$db->quoteName('b.id', 'branch_id'), $db->quoteName('b.title', 'branch_title')])
|
||||
->leftJoin($db->quoteName('#__finder_taxonomy', 'b') . ' ON b.level = 1 AND b.lft <= a.lft AND a.rgt <= b.rgt');
|
||||
|
||||
// Join to get the map links.
|
||||
$stateQuery = $db->getQuery(true)
|
||||
->select('m.node_id')
|
||||
->select('COUNT(NULLIF(l.published, 0)) AS count_published')
|
||||
->select('COUNT(NULLIF(l.published, 1)) AS count_unpublished')
|
||||
->from($db->quoteName('#__finder_taxonomy_map', 'm'))
|
||||
->leftJoin($db->quoteName('#__finder_links', 'l') . ' ON l.link_id = m.link_id')
|
||||
->group('m.node_id');
|
||||
|
||||
$query->select('COALESCE(s.count_published, 0) AS count_published');
|
||||
$query->select('COALESCE(s.count_unpublished, 0) AS count_unpublished');
|
||||
$query->leftJoin('(' . $stateQuery . ') AS s ON s.node_id = a.id');
|
||||
|
||||
// If the model is set to check item state, add to the query.
|
||||
$state = $this->getState('filter.state');
|
||||
|
||||
if (is_numeric($state)) {
|
||||
$query->where('a.state = ' . (int) $state);
|
||||
}
|
||||
|
||||
// Filter over level.
|
||||
$level = $this->getState('filter.level');
|
||||
|
||||
if (is_numeric($level) && (int) $level === 1) {
|
||||
$query->where('a.parent_id = 1');
|
||||
}
|
||||
|
||||
// Filter the maps over the branch if set.
|
||||
$branchId = $this->getState('filter.branch');
|
||||
|
||||
if (is_numeric($branchId)) {
|
||||
$query->where('a.parent_id = ' . (int) $branchId);
|
||||
}
|
||||
|
||||
// Filter the maps over the search string if set.
|
||||
if ($search = $this->getState('filter.search')) {
|
||||
$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
|
||||
$query->where('a.title LIKE ' . $search);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$query->order($db->escape($this->getState('list.ordering', 'branch_title, a.lft')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a record count for the query.
|
||||
*
|
||||
* @param \Joomla\Database\DatabaseQuery|string
|
||||
*
|
||||
* @return integer Number of rows for query.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
protected function _getListCount($query)
|
||||
{
|
||||
$query = clone $query;
|
||||
$query->clear('select')->clear('join')->clear('order')->clear('limit')->clear('offset')->select('COUNT(*)');
|
||||
|
||||
return (int) $this->getDatabase()->setQuery($query)->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* This is necessary because the model is used by the component and
|
||||
* different modules that might need different sets of data or different
|
||||
* ordering requirements.
|
||||
*
|
||||
* @param string $id A prefix for the store id. [optional]
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
$id .= ':' . $this->getState('filter.state');
|
||||
$id .= ':' . $this->getState('filter.branch');
|
||||
$id .= ':' . $this->getState('filter.level');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Table object, always creating it.
|
||||
*
|
||||
* @param string $type The table type to instantiate. [optional]
|
||||
* @param string $prefix A prefix for the table class name. [optional]
|
||||
* @param array $config Configuration array for model. [optional]
|
||||
*
|
||||
* @return \Joomla\CMS\Table\Table A database object
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getTable($type = 'Map', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getTable($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field. [optional]
|
||||
* @param string $direction An optional direction. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function populateState($ordering = 'branch_title, a.lft', $direction = 'ASC')
|
||||
{
|
||||
// Load the filter state.
|
||||
$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
|
||||
$this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd'));
|
||||
$this->setState('filter.branch', $this->getUserStateFromRequest($this->context . '.filter.branch', 'filter_branch', '', 'cmd'));
|
||||
$this->setState('filter.level', $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level', '', 'cmd'));
|
||||
|
||||
// Load the parameters.
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$this->setState('params', $params);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the published state of one or more records.
|
||||
*
|
||||
* @param array $pks A list of the primary keys to change.
|
||||
* @param integer $value The value of the published state. [optional]
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function publish(&$pks, $value = 1)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$table = $this->getTable();
|
||||
$pks = (array) $pks;
|
||||
|
||||
// Include the content plugins for the change of state event.
|
||||
PluginHelper::importPlugin('content');
|
||||
|
||||
// Access checks.
|
||||
foreach ($pks as $i => $pk) {
|
||||
$table->reset();
|
||||
|
||||
if ($table->load($pk) && !$this->canEditState($table)) {
|
||||
// Prune items that you can't change.
|
||||
unset($pks[$i]);
|
||||
$this->setError(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to change the state of the records.
|
||||
if (!$table->publish($pks, $value, $user->get('id'))) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
// Trigger the onContentChangeState event.
|
||||
$result = Factory::getApplication()->triggerEvent('onContentChangeState', [$context, $pks, $value]);
|
||||
|
||||
if (\in_array(false, $result, true)) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear the component's cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to purge all maps from the taxonomy.
|
||||
*
|
||||
* @return boolean Returns true on success, false on failure.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' > 1');
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query->clear()
|
||||
->delete($db->quoteName('#__finder_taxonomy_map'));
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulate the query to be used to evaluate if this is an Empty State to provide specific conditions for this extension.
|
||||
*
|
||||
* @return DatabaseQuery
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getEmptyStateQuery()
|
||||
{
|
||||
$query = parent::getEmptyStateQuery();
|
||||
|
||||
$title = 'ROOT';
|
||||
|
||||
$query->where($this->getDatabase()->quoteName('title') . ' <> :title')
|
||||
->bind(':title', $title);
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
173
administrator/components/com_finder/src/Model/SearchesModel.php
Normal file
173
administrator/components/com_finder/src/Model/SearchesModel.php
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Methods supporting a list of search terms.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class SearchesModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'searchterm', 'a.searchterm',
|
||||
'hits', 'a.hits',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function populateState($ordering = 'a.hits', $direction = 'asc')
|
||||
{
|
||||
// Special state for toggle results button.
|
||||
$this->setState('show_results', $this->getUserStateFromRequest($this->context . '.show_results', 'show_results', 1, 'int'));
|
||||
|
||||
// Load the parameters.
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
$this->setState('params', $params);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* This is necessary because the model is used by the component and
|
||||
* different modules that might need different sets of data or different
|
||||
* ordering requirements.
|
||||
*
|
||||
* @param string $id A prefix for the store id.
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('show_results');
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return \Joomla\Database\DatabaseQuery
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
// Create a new query object.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// Select the required fields from the table.
|
||||
$query->select(
|
||||
$this->getState(
|
||||
'list.select',
|
||||
'a.*'
|
||||
)
|
||||
);
|
||||
$query->from($db->quoteName('#__finder_logging', 'a'));
|
||||
|
||||
// Filter by search in title
|
||||
if ($search = $this->getState('filter.search')) {
|
||||
$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
|
||||
$query->where($db->quoteName('a.searchterm') . ' LIKE ' . $search);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$query->order($db->escape($this->getState('list.ordering', 'a.hits')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the parent getItems to inject optional data.
|
||||
*
|
||||
* @return mixed An array of objects on success, false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$items = parent::getItems();
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (\is_resource($item->query)) {
|
||||
$item->query = unserialize(stream_get_contents($item->query));
|
||||
} else {
|
||||
$item->query = unserialize($item->query);
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to reset the search log table.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
try {
|
||||
$db->truncateTable('#__finder_logging');
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Statistics model class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class StatisticsModel extends BaseDatabaseModel
|
||||
{
|
||||
/**
|
||||
* Method to get the component statistics
|
||||
*
|
||||
* @return CMSObject The component statistics
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
// Initialise
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
$data = new CMSObject();
|
||||
|
||||
$query->select('COUNT(term_id)')
|
||||
->from($db->quoteName('#__finder_terms'));
|
||||
$db->setQuery($query);
|
||||
$data->term_count = $db->loadResult();
|
||||
|
||||
$query->clear()
|
||||
->select('COUNT(link_id)')
|
||||
->from($db->quoteName('#__finder_links'));
|
||||
$db->setQuery($query);
|
||||
$data->link_count = $db->loadResult();
|
||||
|
||||
$query->clear()
|
||||
->select('COUNT(id)')
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' = 1');
|
||||
$db->setQuery($query);
|
||||
$data->taxonomy_branch_count = $db->loadResult();
|
||||
|
||||
$query->clear()
|
||||
->select('COUNT(id)')
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' > 1');
|
||||
$db->setQuery($query);
|
||||
$data->taxonomy_node_count = $db->loadResult();
|
||||
|
||||
$query->clear()
|
||||
->select('t.title AS type_title, COUNT(a.link_id) AS link_count')
|
||||
->from($db->quoteName('#__finder_links') . ' AS a')
|
||||
->join('INNER', $db->quoteName('#__finder_types') . ' AS t ON t.id = a.type_id')
|
||||
->group('a.type_id, t.title')
|
||||
->order($db->quoteName('type_title') . ' ASC');
|
||||
$db->setQuery($query);
|
||||
$data->type_list = $db->loadObjectList();
|
||||
|
||||
$lang = Factory::getLanguage();
|
||||
$plugins = PluginHelper::getPlugin('finder');
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
$lang->load('plg_finder_' . $plugin->name . '.sys', JPATH_ADMINISTRATOR)
|
||||
|| $lang->load('plg_finder_' . $plugin->name . '.sys', JPATH_PLUGINS . '/finder/' . $plugin->name);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
189
administrator/components/com_finder/src/Response/Response.php
Normal file
189
administrator/components/com_finder/src/Response/Response.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Response;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Finder Indexer JSON Response Class
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Response
|
||||
{
|
||||
/**
|
||||
* The buffer
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $buffer;
|
||||
|
||||
/**
|
||||
* The memory
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $memory;
|
||||
|
||||
/**
|
||||
* If it has an error
|
||||
*
|
||||
* @var bool
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $error;
|
||||
|
||||
/**
|
||||
* The header
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $header;
|
||||
|
||||
/**
|
||||
* The message
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* The batch size
|
||||
*
|
||||
* @var int
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $batchSize;
|
||||
|
||||
/**
|
||||
* The batch offset
|
||||
*
|
||||
* @var int
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $batchOffset;
|
||||
|
||||
/**
|
||||
* The total items
|
||||
*
|
||||
* @var int
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $totalItems;
|
||||
|
||||
/**
|
||||
* The plugin state
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $pluginState;
|
||||
|
||||
/**
|
||||
* The start time
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $startTime;
|
||||
|
||||
/**
|
||||
* The end time
|
||||
*
|
||||
* @var string
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $endTime;
|
||||
|
||||
/**
|
||||
* The start
|
||||
*
|
||||
* @var int
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $start;
|
||||
|
||||
/**
|
||||
* The complete
|
||||
*
|
||||
* @var int
|
||||
* @since 4.3.0
|
||||
*/
|
||||
public $complete;
|
||||
|
||||
/**
|
||||
* Class Constructor
|
||||
*
|
||||
* @param mixed $state The processing state for the indexer
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct($state)
|
||||
{
|
||||
$params = ComponentHelper::getParams('com_finder');
|
||||
|
||||
if ($params->get('enable_logging', '0')) {
|
||||
$options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}';
|
||||
$options['text_file'] = 'indexer.php';
|
||||
Log::addLogger($options);
|
||||
}
|
||||
|
||||
// Check if we are dealing with an error.
|
||||
if ($state instanceof \Exception) {
|
||||
// Log the error
|
||||
try {
|
||||
Log::add($state->getMessage(), Log::ERROR);
|
||||
} catch (\RuntimeException $exception) {
|
||||
// Informational log only
|
||||
}
|
||||
|
||||
// Prepare the error response.
|
||||
$this->error = true;
|
||||
$this->header = Text::_('COM_FINDER_INDEXER_HEADER_ERROR');
|
||||
$this->message = $state->getMessage();
|
||||
} else {
|
||||
// Prepare the response data.
|
||||
$this->batchSize = (int) $state->batchSize;
|
||||
$this->batchOffset = (int) $state->batchOffset;
|
||||
$this->totalItems = (int) $state->totalItems;
|
||||
$this->pluginState = $state->pluginState;
|
||||
|
||||
$this->startTime = $state->startTime;
|
||||
$this->endTime = Factory::getDate()->toSql();
|
||||
|
||||
$this->start = !empty($state->start) ? (int) $state->start : 0;
|
||||
$this->complete = !empty($state->complete) ? (int) $state->complete : 0;
|
||||
|
||||
// Set the appropriate messages.
|
||||
if ($this->totalItems <= 0 && $this->complete) {
|
||||
$this->header = Text::_('COM_FINDER_INDEXER_HEADER_COMPLETE');
|
||||
$this->message = Text::_('COM_FINDER_INDEXER_MESSAGE_COMPLETE');
|
||||
} elseif ($this->totalItems <= 0) {
|
||||
$this->header = Text::_('COM_FINDER_INDEXER_HEADER_OPTIMIZE');
|
||||
$this->message = Text::_('COM_FINDER_INDEXER_MESSAGE_OPTIMIZE');
|
||||
} else {
|
||||
$this->header = Text::_('COM_FINDER_INDEXER_HEADER_RUNNING');
|
||||
$this->message = Text::_('COM_FINDER_INDEXER_MESSAGE_RUNNING');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
496
administrator/components/com_finder/src/Service/HTML/Filter.php
Normal file
496
administrator/components/com_finder/src/Service/HTML/Filter.php
Normal file
@ -0,0 +1,496 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Query;
|
||||
use Joomla\Database\DatabaseAwareTrait;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Filter\OutputFilter;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filter HTML Behaviors for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Filter
|
||||
{
|
||||
use DatabaseAwareTrait;
|
||||
|
||||
/**
|
||||
* Method to generate filters using the slider widget and decorated
|
||||
* with the FinderFilter JavaScript behaviors.
|
||||
*
|
||||
* @param array $options An array of configuration options. [optional]
|
||||
*
|
||||
* @return mixed A rendered HTML widget on success, null otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function slider($options = [])
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
$user = Factory::getUser();
|
||||
$groups = implode(',', $user->getAuthorisedViewLevels());
|
||||
$html = '';
|
||||
$filter = null;
|
||||
|
||||
// Get the configuration options.
|
||||
$filterId = $options['filter_id'] ?? null;
|
||||
$activeNodes = \array_key_exists('selected_nodes', $options) ? $options['selected_nodes'] : [];
|
||||
$classSuffix = \array_key_exists('class_suffix', $options) ? $options['class_suffix'] : '';
|
||||
|
||||
// Load the predefined filter if specified.
|
||||
if (!empty($filterId)) {
|
||||
$query->select('f.data, f.params')
|
||||
->from($db->quoteName('#__finder_filters') . ' AS f')
|
||||
->where('f.filter_id = ' . (int) $filterId);
|
||||
|
||||
// Load the filter data.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$filter = $db->loadObject();
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Initialize the filter parameters.
|
||||
if ($filter) {
|
||||
$filter->params = new Registry($filter->params);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the query to get the branch data and the number of child nodes.
|
||||
$query->clear()
|
||||
->select('t.*, count(c.id) AS children')
|
||||
->from($db->quoteName('#__finder_taxonomy') . ' AS t')
|
||||
->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id')
|
||||
->where('t.parent_id = 1')
|
||||
->where('t.state = 1')
|
||||
->where('t.access IN (' . $groups . ')')
|
||||
->group('t.id, t.parent_id, t.state, t.access, t.title, c.parent_id')
|
||||
->order('t.lft, t.title');
|
||||
|
||||
// Limit the branch children to a predefined filter.
|
||||
if ($filter) {
|
||||
$query->where('c.id IN(' . $filter->data . ')');
|
||||
}
|
||||
|
||||
// Load the branches.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$branches = $db->loadObjectList('id');
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check that we have at least one branch.
|
||||
if (\count($branches) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$branch_keys = array_keys($branches);
|
||||
$html .= HTMLHelper::_('bootstrap.startAccordion', 'accordion', ['active' => 'accordion-' . $branch_keys[0]]);
|
||||
|
||||
// Load plugin language files.
|
||||
LanguageHelper::loadPluginLanguage();
|
||||
|
||||
// Iterate through the branches and build the branch groups.
|
||||
foreach ($branches as $bk => $bv) {
|
||||
// If the multi-lang plugin is enabled then drop the language branch.
|
||||
if ($bv->title === 'Language' && Multilanguage::isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build the query to get the child nodes for this branch.
|
||||
$query->clear()
|
||||
->select('t.*')
|
||||
->from($db->quoteName('#__finder_taxonomy') . ' AS t')
|
||||
->where('t.lft > ' . (int) $bv->lft)
|
||||
->where('t.rgt < ' . (int) $bv->rgt)
|
||||
->where('t.state = 1')
|
||||
->where('t.access IN (' . $groups . ')')
|
||||
->order('t.lft, t.title');
|
||||
|
||||
// Self-join to get the parent title.
|
||||
$query->select('e.title AS parent_title')
|
||||
->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id'));
|
||||
|
||||
// Load the branches.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$nodes = $db->loadObjectList('id');
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Translate node titles if possible.
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
foreach ($nodes as $nk => $nv) {
|
||||
if (trim($nv->parent_title, '*') === 'Language') {
|
||||
$title = LanguageHelper::branchLanguageTitle($nv->title);
|
||||
} else {
|
||||
$key = LanguageHelper::branchPlural($nv->title);
|
||||
$title = $lang->hasKey($key) ? Text::_($key) : $nv->title;
|
||||
}
|
||||
|
||||
$nodes[$nk]->title = $title;
|
||||
}
|
||||
|
||||
// Adding slides
|
||||
$html .= HTMLHelper::_(
|
||||
'bootstrap.addSlide',
|
||||
'accordion',
|
||||
Text::sprintf(
|
||||
'COM_FINDER_FILTER_BRANCH_LABEL',
|
||||
Text::_(LanguageHelper::branchSingular($bv->title)) . ' - ' . \count($nodes)
|
||||
),
|
||||
'accordion-' . $bk
|
||||
);
|
||||
|
||||
// Populate the toggle button.
|
||||
$html .= '<button class="btn btn-secondary js-filter" type="button" data-id="tax-' . $bk . '"><span class="icon-square" aria-hidden="true"></span> '
|
||||
. Text::_('JGLOBAL_SELECTION_INVERT') . '</button><hr>';
|
||||
|
||||
// Populate the group with nodes.
|
||||
foreach ($nodes as $nk => $nv) {
|
||||
// Determine if the node should be checked.
|
||||
$checked = \in_array($nk, $activeNodes) ? ' checked="checked"' : '';
|
||||
|
||||
// Build a node.
|
||||
$html .= '<div class="form-check">';
|
||||
$html .= '<label class="form-check-label">';
|
||||
$html .= '<input type="checkbox" class="form-check-input selector filter-node' . $classSuffix
|
||||
. ' tax-' . $bk . '" value="' . $nk . '" name="t[]"' . $checked . '> ' . str_repeat('—', $nv->level - 2) . $nv->title;
|
||||
$html .= '</label>';
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
$html .= HTMLHelper::_('bootstrap.endSlide');
|
||||
}
|
||||
|
||||
$html .= HTMLHelper::_('bootstrap.endAccordion');
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate filters using select box dropdown controls.
|
||||
*
|
||||
* @param Query $idxQuery A Query object.
|
||||
* @param Registry $options An array of options.
|
||||
*
|
||||
* @return string|null A rendered HTML widget on success, null otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function select($idxQuery, $options)
|
||||
{
|
||||
$user = Factory::getUser();
|
||||
$groups = implode(',', $user->getAuthorisedViewLevels());
|
||||
$filter = null;
|
||||
|
||||
// Get the configuration options.
|
||||
$classSuffix = $options->get('class_suffix', null);
|
||||
$showDates = $options->get('show_date_filters', false);
|
||||
|
||||
// Try to load the results from cache.
|
||||
$cache = Factory::getCache('com_finder', '');
|
||||
$cacheId = 'filter_select_' . serialize([$idxQuery->filter, $options, $groups, Factory::getLanguage()->getTag()]);
|
||||
|
||||
// Check the cached results.
|
||||
if ($cache->contains($cacheId)) {
|
||||
$branches = $cache->get($cacheId);
|
||||
} else {
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// Load the predefined filter if specified.
|
||||
if (!empty($idxQuery->filter)) {
|
||||
$query->select('f.data, ' . $db->quoteName('f.params'))
|
||||
->from($db->quoteName('#__finder_filters') . ' AS f')
|
||||
->where('f.filter_id = ' . (int) $idxQuery->filter);
|
||||
|
||||
// Load the filter data.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$filter = $db->loadObject();
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Initialize the filter parameters.
|
||||
if ($filter) {
|
||||
$filter->params = new Registry($filter->params);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the query to get the branch data and the number of child nodes.
|
||||
$query->clear()
|
||||
->select('t.*, count(c.id) AS children')
|
||||
->from($db->quoteName('#__finder_taxonomy') . ' AS t')
|
||||
->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id')
|
||||
->where('t.parent_id = 1')
|
||||
->where('t.state = 1')
|
||||
->where('t.access IN (' . $groups . ')')
|
||||
->where('c.state = 1')
|
||||
->where('c.access IN (' . $groups . ')')
|
||||
->group($db->quoteName('t.id'))
|
||||
->group($db->quoteName('t.parent_id'))
|
||||
->group('t.title, t.state, t.access, t.lft')
|
||||
->order('t.lft, t.title');
|
||||
|
||||
// Limit the branch children to a predefined filter.
|
||||
if (!empty($filter->data)) {
|
||||
$query->where('c.id IN(' . $filter->data . ')');
|
||||
}
|
||||
|
||||
// Load the branches.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$branches = $db->loadObjectList('id');
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check that we have at least one branch.
|
||||
if (\count($branches) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Iterate through the branches and build the branch groups.
|
||||
foreach ($branches as $bk => $bv) {
|
||||
// If the multi-lang plugin is enabled then drop the language branch.
|
||||
if ($bv->title === 'Language' && Multilanguage::isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build the query to get the child nodes for this branch.
|
||||
$query->clear()
|
||||
->select('t.*')
|
||||
->from($db->quoteName('#__finder_taxonomy') . ' AS t')
|
||||
->where('t.lft > :lft')
|
||||
->where('t.rgt < :rgt')
|
||||
->where('t.state = 1')
|
||||
->whereIn('t.access', $user->getAuthorisedViewLevels())
|
||||
->order('t.title')
|
||||
->bind(':lft', $bv->lft, ParameterType::INTEGER)
|
||||
->bind(':rgt', $bv->rgt, ParameterType::INTEGER);
|
||||
|
||||
// Apply multilanguage filter
|
||||
if (Multilanguage::isEnabled()) {
|
||||
$language = [Factory::getLanguage()->getTag(), '*'];
|
||||
$query->whereIn($db->quoteName('t.language'), $language, ParameterType::STRING);
|
||||
}
|
||||
|
||||
// Self-join to get the parent title.
|
||||
$query->select('e.title AS parent_title')
|
||||
->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id'));
|
||||
|
||||
// Limit the nodes to a predefined filter.
|
||||
if (!empty($filter->data)) {
|
||||
$query->whereIn('t.id', explode(",", $filter->data));
|
||||
}
|
||||
|
||||
// Load the branches.
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$branches[$bk]->nodes = $db->loadObjectList('id');
|
||||
} catch (\RuntimeException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Translate branch nodes if possible.
|
||||
$language = Factory::getLanguage();
|
||||
|
||||
foreach ($branches[$bk]->nodes as $node_id => $node) {
|
||||
if (trim($node->parent_title, '*') === 'Language') {
|
||||
$title = LanguageHelper::branchLanguageTitle($node->title);
|
||||
} else {
|
||||
$key = LanguageHelper::branchPlural($node->title);
|
||||
$title = $language->hasKey($key) ? Text::_($key) : $node->title;
|
||||
}
|
||||
|
||||
if ($node->level > 2) {
|
||||
$branches[$bk]->nodes[$node_id]->title = str_repeat('-', $node->level - 2) . $title;
|
||||
} else {
|
||||
$branches[$bk]->nodes[$node_id]->title = $title;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the Search All option to the branch.
|
||||
array_unshift($branches[$bk]->nodes, ['id' => null, 'title' => Text::_('COM_FINDER_FILTER_SELECT_ALL_LABEL')]);
|
||||
}
|
||||
|
||||
// Store the data in cache.
|
||||
$cache->store($branches, $cacheId);
|
||||
}
|
||||
|
||||
$html = '';
|
||||
|
||||
// Add the dates if enabled.
|
||||
if ($showDates) {
|
||||
$html .= HTMLHelper::_('filter.dates', $idxQuery, $options);
|
||||
}
|
||||
|
||||
$html .= '<div class="filter-branch' . $classSuffix . '">';
|
||||
|
||||
// Iterate through all branches and build code.
|
||||
foreach ($branches as $bk => $bv) {
|
||||
// If the multi-lang plugin is enabled then drop the language branch.
|
||||
if ($bv->title === 'Language' && Multilanguage::isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$active = null;
|
||||
|
||||
// Check if the branch is in the filter.
|
||||
if (\array_key_exists($bv->title, $idxQuery->filters)) {
|
||||
// Get the request filters.
|
||||
$temp = Factory::getApplication()->getInput()->request->get('t', [], 'array');
|
||||
|
||||
// Search for active nodes in the branch and get the active node.
|
||||
$active = array_intersect($temp, $idxQuery->filters[$bv->title]);
|
||||
$active = \count($active) === 1 ? array_shift($active) : null;
|
||||
}
|
||||
|
||||
// Build a node.
|
||||
$html .= '<div class="control-group">';
|
||||
$html .= '<div class="control-label">';
|
||||
$html .= '<label for="tax-' . OutputFilter::stringURLSafe($bv->title) . '">';
|
||||
$html .= Text::sprintf('COM_FINDER_FILTER_BRANCH_LABEL', Text::_(LanguageHelper::branchSingular($bv->title)));
|
||||
$html .= '</label>';
|
||||
$html .= '</div>';
|
||||
$html .= '<div class="controls">';
|
||||
$html .= HTMLHelper::_(
|
||||
'select.genericlist',
|
||||
$branches[$bk]->nodes,
|
||||
't[]',
|
||||
'class="form-select advancedSelect"',
|
||||
'id',
|
||||
'title',
|
||||
$active,
|
||||
'tax-' . OutputFilter::stringURLSafe($bv->title)
|
||||
);
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate fields for filtering dates
|
||||
*
|
||||
* @param Query $idxQuery A Query object.
|
||||
* @param Registry $options An array of options.
|
||||
*
|
||||
* @return string A rendered HTML widget.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function dates($idxQuery, $options)
|
||||
{
|
||||
$html = '';
|
||||
|
||||
// Get the configuration options.
|
||||
$classSuffix = $options->get('class_suffix', null);
|
||||
$loadMedia = $options->get('load_media', true);
|
||||
$showDates = $options->get('show_date_filters', false);
|
||||
|
||||
if (!empty($showDates)) {
|
||||
// Build the date operators options.
|
||||
$operators = [];
|
||||
$operators[] = HTMLHelper::_('select.option', 'before', Text::_('COM_FINDER_FILTER_DATE_BEFORE'));
|
||||
$operators[] = HTMLHelper::_('select.option', 'exact', Text::_('COM_FINDER_FILTER_DATE_EXACTLY'));
|
||||
$operators[] = HTMLHelper::_('select.option', 'after', Text::_('COM_FINDER_FILTER_DATE_AFTER'));
|
||||
|
||||
// Load the CSS/JS resources.
|
||||
if ($loadMedia) {
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
|
||||
$wa->useStyle('com_finder.dates');
|
||||
}
|
||||
|
||||
// Open the widget.
|
||||
$html .= '<ul id="finder-filter-select-dates">';
|
||||
|
||||
// Start date filter.
|
||||
$attribs['class'] = 'input-medium';
|
||||
$html .= '<li class="filter-date float-start' . $classSuffix . '">';
|
||||
$html .= '<label for="filter_date1" class="hasTooltip" title ="' . Text::_('COM_FINDER_FILTER_DATE1_DESC') . '">';
|
||||
$html .= Text::_('COM_FINDER_FILTER_DATE1');
|
||||
$html .= '</label>';
|
||||
$html .= '<br>';
|
||||
$html .= '<label for="finder-filter-w1" class="visually-hidden">';
|
||||
$html .= Text::_('COM_FINDER_FILTER_DATE1_OPERATOR');
|
||||
$html .= '</label>';
|
||||
$html .= HTMLHelper::_(
|
||||
'select.genericlist',
|
||||
$operators,
|
||||
'w1',
|
||||
'class="inputbox filter-date-operator advancedSelect form-select w-auto mb-2"',
|
||||
'value',
|
||||
'text',
|
||||
$idxQuery->when1,
|
||||
'finder-filter-w1'
|
||||
);
|
||||
$html .= HTMLHelper::_('calendar', $idxQuery->date1, 'd1', 'filter_date1', '%Y-%m-%d', $attribs);
|
||||
$html .= '</li>';
|
||||
|
||||
// End date filter.
|
||||
$html .= '<li class="filter-date float-end' . $classSuffix . '">';
|
||||
$html .= '<label for="filter_date2" class="hasTooltip" title ="' . Text::_('COM_FINDER_FILTER_DATE2_DESC') . '">';
|
||||
$html .= Text::_('COM_FINDER_FILTER_DATE2');
|
||||
$html .= '</label>';
|
||||
$html .= '<br>';
|
||||
$html .= '<label for="finder-filter-w2" class="visually-hidden">';
|
||||
$html .= Text::_('COM_FINDER_FILTER_DATE2_OPERATOR');
|
||||
$html .= '</label>';
|
||||
$html .= HTMLHelper::_(
|
||||
'select.genericlist',
|
||||
$operators,
|
||||
'w2',
|
||||
'class="inputbox filter-date-operator advancedSelect form-select w-auto mb-2"',
|
||||
'value',
|
||||
'text',
|
||||
$idxQuery->when2,
|
||||
'finder-filter-w2'
|
||||
);
|
||||
$html .= HTMLHelper::_('calendar', $idxQuery->date2, 'd2', 'filter_date2', '%Y-%m-%d', $attribs);
|
||||
$html .= '</li>';
|
||||
|
||||
// Close the widget.
|
||||
$html .= '</ul>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
131
administrator/components/com_finder/src/Service/HTML/Finder.php
Normal file
131
administrator/components/com_finder/src/Service/HTML/Finder.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
use Joomla\Database\DatabaseAwareTrait;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* HTML behavior class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Finder
|
||||
{
|
||||
use DatabaseAwareTrait;
|
||||
|
||||
/**
|
||||
* Creates a list of types to filter on.
|
||||
*
|
||||
* @return array An array containing the types that can be selected.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function typeslist()
|
||||
{
|
||||
// Load the finder types.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('DISTINCT t.title AS text, t.id AS value')
|
||||
->from($db->quoteName('#__finder_types') . ' AS t')
|
||||
->join('LEFT', $db->quoteName('#__finder_links') . ' AS l ON l.type_id = t.id')
|
||||
->order('t.title ASC');
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$rows = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Compile the options.
|
||||
$options = [];
|
||||
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$key = $lang->hasKey(LanguageHelper::branchPlural($row->text)) ? LanguageHelper::branchPlural($row->text) : $row->text;
|
||||
$options[] = HTMLHelper::_('select.option', $row->value, Text::sprintf('COM_FINDER_ITEM_X_ONLY', Text::_($key)));
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of maps.
|
||||
*
|
||||
* @return array An array containing the maps that can be selected.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function mapslist()
|
||||
{
|
||||
// Load the finder types.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('title', 'text'))
|
||||
->select($db->quoteName('id', 'value'))
|
||||
->from($db->quoteName('#__finder_taxonomy'))
|
||||
->where($db->quoteName('parent_id') . ' = 1');
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$branches = $db->loadObjectList();
|
||||
} catch (\RuntimeException $e) {
|
||||
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
// Translate.
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
foreach ($branches as $branch) {
|
||||
$key = LanguageHelper::branchPlural($branch->text);
|
||||
$branch->translatedText = $lang->hasKey($key) ? Text::_($key) : $branch->text;
|
||||
}
|
||||
|
||||
// Order by title.
|
||||
$branches = ArrayHelper::sortObjects($branches, 'translatedText', 1, true, true);
|
||||
|
||||
// Compile the options.
|
||||
$options = [];
|
||||
$options[] = HTMLHelper::_('select.option', '', Text::_('COM_FINDER_MAPS_SELECT_BRANCH'));
|
||||
|
||||
// Convert the values to options.
|
||||
foreach ($branches as $branch) {
|
||||
$options[] = HTMLHelper::_('select.option', $branch->value, $branch->translatedText);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of published states.
|
||||
*
|
||||
* @return array An array containing the states that can be selected.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function statelist()
|
||||
{
|
||||
return [
|
||||
HTMLHelper::_('select.option', '1', Text::sprintf('COM_FINDER_ITEM_X_ONLY', Text::_('JPUBLISHED'))),
|
||||
HTMLHelper::_('select.option', '0', Text::sprintf('COM_FINDER_ITEM_X_ONLY', Text::_('JUNPUBLISHED'))),
|
||||
];
|
||||
}
|
||||
}
|
||||
156
administrator/components/com_finder/src/Service/HTML/Query.php
Normal file
156
administrator/components/com_finder/src/Service/HTML/Query.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
use Joomla\Component\Finder\Administrator\Indexer\Query as IndexerQuery;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Query HTML behavior class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Query
|
||||
{
|
||||
/**
|
||||
* Method to get the explained (human-readable) search query.
|
||||
*
|
||||
* @param IndexerQuery $query A IndexerQuery object to explain.
|
||||
*
|
||||
* @return mixed String if there is data to explain, null otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function explained(IndexerQuery $query)
|
||||
{
|
||||
$parts = [];
|
||||
|
||||
// Process the required tokens.
|
||||
foreach ($query->included as $token) {
|
||||
if ($token->required && (!isset($token->derived) || $token->derived == false)) {
|
||||
$parts[] = '<span class="query-required">' . Text::sprintf('COM_FINDER_QUERY_TOKEN_REQUIRED', $token->term) . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Process the optional tokens.
|
||||
foreach ($query->included as $token) {
|
||||
if (!$token->required && (!isset($token->derived) || $token->derived == false)) {
|
||||
$parts[] = '<span class="query-optional">' . Text::sprintf('COM_FINDER_QUERY_TOKEN_OPTIONAL', $token->term) . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Process the excluded tokens.
|
||||
foreach ($query->excluded as $token) {
|
||||
if (!isset($token->derived) || $token->derived === false) {
|
||||
$parts[] = '<span class="query-excluded">' . Text::sprintf('COM_FINDER_QUERY_TOKEN_EXCLUDED', $token->term) . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Process the start date.
|
||||
if ($query->date1) {
|
||||
$date = Factory::getDate($query->date1)->format(Text::_('DATE_FORMAT_LC'));
|
||||
$datecondition = Text::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when1));
|
||||
$parts[] = '<span class="query-start-date">' . Text::sprintf('COM_FINDER_QUERY_START_DATE', $datecondition, $date) . '</span>';
|
||||
}
|
||||
|
||||
// Process the end date.
|
||||
if ($query->date2) {
|
||||
$date = Factory::getDate($query->date2)->format(Text::_('DATE_FORMAT_LC'));
|
||||
$datecondition = Text::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when2));
|
||||
$parts[] = '<span class="query-end-date">' . Text::sprintf('COM_FINDER_QUERY_END_DATE', $datecondition, $date) . '</span>';
|
||||
}
|
||||
|
||||
// Process the taxonomy filters.
|
||||
if (!empty($query->filters)) {
|
||||
// Get the filters in the request.
|
||||
$t = Factory::getApplication()->getInput()->request->get('t', [], 'array');
|
||||
|
||||
// Process the taxonomy branches.
|
||||
foreach ($query->filters as $branch => $nodes) {
|
||||
// Process the taxonomy nodes.
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
foreach ($nodes as $title => $id) {
|
||||
// Translate the title for Types
|
||||
$key = LanguageHelper::branchPlural($title);
|
||||
|
||||
if ($lang->hasKey($key)) {
|
||||
$title = Text::_($key);
|
||||
}
|
||||
|
||||
// Don't include the node if it is not in the request.
|
||||
if (!\in_array($id, $t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the node to the explanation.
|
||||
$parts[] = '<span class="query-taxonomy">'
|
||||
. Text::sprintf('COM_FINDER_QUERY_TAXONOMY_NODE', $title, Text::_(LanguageHelper::branchSingular($branch)))
|
||||
. '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the interpreted query.
|
||||
return \count($parts) ? implode(Text::_('COM_FINDER_QUERY_TOKEN_GLUE'), $parts) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the suggested search query.
|
||||
*
|
||||
* @param IndexerQuery $query A IndexerQuery object.
|
||||
*
|
||||
* @return mixed String if there is a suggestion, false otherwise.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function suggested(IndexerQuery $query)
|
||||
{
|
||||
$suggested = false;
|
||||
|
||||
// Check if the query input is empty.
|
||||
if (empty($query->input)) {
|
||||
return $suggested;
|
||||
}
|
||||
|
||||
// Check if there were any ignored or included keywords.
|
||||
if (\count($query->ignored) || \count($query->included)) {
|
||||
$suggested = $query->input;
|
||||
|
||||
// Replace the ignored keyword suggestions.
|
||||
foreach (array_reverse($query->ignored) as $token) {
|
||||
if (isset($token->suggestion)) {
|
||||
$suggested = str_ireplace($token->term, $token->suggestion, $suggested);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the included keyword suggestions.
|
||||
foreach (array_reverse($query->included) as $token) {
|
||||
if (isset($token->suggestion)) {
|
||||
$suggested = str_ireplace($token->term, $token->suggestion, $suggested);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we made any changes.
|
||||
if ($suggested == $query->input) {
|
||||
$suggested = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $suggested;
|
||||
}
|
||||
}
|
||||
173
administrator/components/com_finder/src/Table/FilterTable.php
Normal file
173
administrator/components/com_finder/src/Table/FilterTable.php
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\CMS\User\CurrentUserInterface;
|
||||
use Joomla\CMS\User\CurrentUserTrait;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filter table class for the Finder package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class FilterTable extends Table implements CurrentUserInterface
|
||||
{
|
||||
use CurrentUserTrait;
|
||||
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* Ensure the params are json encoded in the bind method
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_jsonEncode = ['params'];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct('#__finder_filters', 'filter_id', $db, $dispatcher);
|
||||
|
||||
$this->setColumnAlias('published', 'state');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to perform sanity checks on the \Joomla\CMS\Table\Table instance properties to ensure
|
||||
* they are safe to store in the database. Child classes should override this
|
||||
* method to make sure the data they are storing in the database is safe and
|
||||
* as expected before storage.
|
||||
*
|
||||
* @return boolean True if the instance is sane and able to be stored in the database.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
try {
|
||||
parent::check();
|
||||
} catch (\Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trim($this->alias) === '') {
|
||||
$this->alias = $this->title;
|
||||
}
|
||||
|
||||
$this->alias = ApplicationHelper::stringURLSafe($this->alias);
|
||||
|
||||
if (trim(str_replace('-', '', $this->alias)) === '') {
|
||||
$this->alias = Factory::getDate()->format('Y-m-d-H-i-s');
|
||||
}
|
||||
|
||||
$params = new Registry($this->params);
|
||||
|
||||
$d1 = $params->get('d1', '');
|
||||
$d2 = $params->get('d2', '');
|
||||
|
||||
// Check the end date is not earlier than the start date.
|
||||
if (!empty($d1) && !empty($d2) && $d2 < $d1) {
|
||||
// Swap the dates.
|
||||
$params->set('d1', $d2);
|
||||
$params->set('d2', $d1);
|
||||
$this->params = (string) $params;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to store a row in the database from the \Joomla\CMS\Table\Table instance properties.
|
||||
* If a primary key value is set the row with that primary key value will be
|
||||
* updated with the instance property values. If no primary key value is set
|
||||
* a new row will be inserted into the database with the properties from the
|
||||
* \Joomla\CMS\Table\Table instance.
|
||||
*
|
||||
* @param boolean $updateNulls True to update fields even if they are null. [optional]
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function store($updateNulls = true)
|
||||
{
|
||||
$date = Factory::getDate()->toSql();
|
||||
$userId = $this->getCurrentUser()->id;
|
||||
|
||||
// Set created date if not set.
|
||||
if (!(int) $this->created) {
|
||||
$this->created = $date;
|
||||
}
|
||||
|
||||
if ($this->filter_id) {
|
||||
// Existing item
|
||||
$this->modified_by = $userId;
|
||||
$this->modified = $date;
|
||||
} else {
|
||||
if (empty($this->created_by)) {
|
||||
$this->created_by = $userId;
|
||||
}
|
||||
|
||||
if (!(int) $this->modified) {
|
||||
$this->modified = $this->created;
|
||||
}
|
||||
|
||||
if (empty($this->modified_by)) {
|
||||
$this->modified_by = $this->created_by;
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_array($this->data)) {
|
||||
$this->map_count = \count($this->data);
|
||||
$this->data = implode(',', $this->data);
|
||||
} else {
|
||||
$this->map_count = 0;
|
||||
$this->data = implode(',', []);
|
||||
}
|
||||
|
||||
// Verify that the alias is unique
|
||||
$table = new self($this->getDbo(), $this->getDispatcher());
|
||||
|
||||
if ($table->load(['alias' => $this->alias]) && ($table->filter_id != $this->filter_id || $this->filter_id == 0)) {
|
||||
$this->setError(Text::_('COM_FINDER_FILTER_ERROR_UNIQUE_ALIAS'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::store($updateNulls);
|
||||
}
|
||||
}
|
||||
63
administrator/components/com_finder/src/Table/LinkTable.php
Normal file
63
administrator/components/com_finder/src/Table/LinkTable.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Link table class for the Finder package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class LinkTable extends Table
|
||||
{
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct('#__finder_links', 'link_id', $db, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded store function
|
||||
*
|
||||
* @param boolean $updateNulls True to update fields even if they are null.
|
||||
*
|
||||
* @return mixed False on failure, positive integer on success.
|
||||
*
|
||||
* @see Table::store()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function store($updateNulls = true)
|
||||
{
|
||||
return parent::store($updateNulls);
|
||||
}
|
||||
}
|
||||
80
administrator/components/com_finder/src/Table/MapTable.php
Normal file
80
administrator/components/com_finder/src/Table/MapTable.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Table\Nested;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Map table class for the Finder package.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class MapTable extends Nested
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct('#__finder_taxonomy', 'id', $db, $dispatcher);
|
||||
|
||||
$this->setColumnAlias('published', 'state');
|
||||
$this->access = (int) Factory::getApplication()->get('access');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override check function
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @see Table::check()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
try {
|
||||
parent::check();
|
||||
} catch (\Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a title.
|
||||
if (trim($this->title) == '') {
|
||||
$this->setError(Text::_('JLIB_DATABASE_ERROR_MUSTCONTAIN_A_TITLE_CATEGORY'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->alias = ApplicationHelper::stringURLSafe($this->title, $this->language);
|
||||
|
||||
if (trim($this->alias) == '') {
|
||||
$this->alias = md5(serialize($this->getProperties()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
178
administrator/components/com_finder/src/View/Filter/HtmlView.php
Normal file
178
administrator/components/com_finder/src/View/Filter/HtmlView.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Filter;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filter view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The filter object
|
||||
*
|
||||
* @var \Joomla\Component\Finder\Administrator\Table\FilterTable
|
||||
*
|
||||
* @since 3.6.2
|
||||
*/
|
||||
protected $filter;
|
||||
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 3.6.2
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The active item
|
||||
*
|
||||
* @var CMSObject|boolean
|
||||
*
|
||||
* @since 3.6.2
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*
|
||||
* @since 3.6.2
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The total indexed items
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 3.8.0
|
||||
*/
|
||||
protected $total;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Load the view data.
|
||||
$this->filter = $this->get('Filter');
|
||||
$this->item = $this->get('Item');
|
||||
$this->form = $this->get('Form');
|
||||
$this->state = $this->get('State');
|
||||
$this->total = $this->get('Total');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Configure the toolbar.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
Factory::getApplication()->getInput()->set('hidemainmenu', true);
|
||||
|
||||
$isNew = ($this->item->filter_id == 0);
|
||||
$checkedOut = !(\is_null($this->item->checked_out) || $this->item->checked_out == $this->getCurrentUser()->id);
|
||||
$canDo = ContentHelper::getActions('com_finder');
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
// Configure the toolbar.
|
||||
ToolbarHelper::title(
|
||||
$isNew ? Text::_('COM_FINDER_FILTER_NEW_TOOLBAR_TITLE') : Text::_('COM_FINDER_FILTER_EDIT_TOOLBAR_TITLE'),
|
||||
'zoom-in finder'
|
||||
);
|
||||
|
||||
// Set the actions for new and existing records.
|
||||
if ($isNew) {
|
||||
// For new records, check the create permission.
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->apply('filter.apply');
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) {
|
||||
$childBar->save('filter.save');
|
||||
$childBar->save2new('filter.save2new');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('filter.cancel', 'JTOOLBAR_CANCEL');
|
||||
} else {
|
||||
// Can't save the record if it's checked out.
|
||||
// Since it's an existing record, check the edit permission.
|
||||
if (!$checkedOut && $canDo->get('core.edit')) {
|
||||
$toolbar->apply('filter.apply');
|
||||
}
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($checkedOut, $canDo) {
|
||||
// Can't save the record if it's checked out.
|
||||
// Since it's an existing record, check the edit permission.
|
||||
if (!$checkedOut && $canDo->get('core.edit')) {
|
||||
$childBar->save('filter.save');
|
||||
|
||||
// We can save this record, but check the create permission to see if we can return to make a new one.
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2new('filter.save2new');
|
||||
}
|
||||
}
|
||||
|
||||
// If an existing item, can save as a copy
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2copy('filter.save2copy');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$toolbar->cancel('filter.cancel');
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
$toolbar->help('Smart_Search:_New_or_Edit_Filter');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Filters;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Filters view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The total number of items
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $total;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Load the view data.
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->total = $this->get('Total');
|
||||
$this->state = $this->get('State');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
if (\count($this->items) === 0 && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Configure the toolbar.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_finder');
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_FILTERS_TOOLBAR_TITLE'), 'search-plus finder');
|
||||
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->addNew('filter.add');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
if ($this->isEmptyState === false) {
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('filters.publish')->listCheck(true);
|
||||
$childBar->unpublish('filters.unpublish')->listCheck(true);
|
||||
$childBar->checkin('filters.checkin')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.delete')) {
|
||||
$toolbar->standardButton('delete', 'JTOOLBAR_DELETE', 'filters.delete')
|
||||
->listCheck(true);
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
$toolbar->popupButton('bars', 'COM_FINDER_STATISTICS')
|
||||
->url('index.php?option=com_finder&view=statistics&tmpl=component')
|
||||
->iframeWidth(550)
|
||||
->iframeHeight(350)
|
||||
->title(Text::_('COM_FINDER_STATISTICS_TITLE'))
|
||||
->icon('icon-bars');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences('com_finder');
|
||||
}
|
||||
|
||||
$toolbar->help('Smart_Search:_Search_Filters');
|
||||
}
|
||||
}
|
||||
264
administrator/components/com_finder/src/View/Index/HtmlView.php
Normal file
264
administrator/components/com_finder/src/View/Index/HtmlView.php
Normal file
@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Index;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Finder\Administrator\Helper\FinderHelper;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Index view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The state of core Smart Search plugins
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $pluginState;
|
||||
|
||||
/**
|
||||
* The id of the content - finder plugin in mysql
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $finderPluginId = 0;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var mixed
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The total number of items
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $total;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Load plugin language files.
|
||||
LanguageHelper::loadPluginLanguage();
|
||||
|
||||
$this->items = $this->get('Items');
|
||||
$this->total = $this->get('Total');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
$this->pluginState = $this->get('pluginState');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
if ($this->get('TotalIndexed') === 0 && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// We do not need to filter by language when multilingual is disabled
|
||||
if (!Multilanguage::isEnabled()) {
|
||||
unset($this->activeFilters['language']);
|
||||
$this->filterForm->removeField('language', 'filter');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check that the content - finder plugin is enabled
|
||||
if (!PluginHelper::isEnabled('content', 'finder')) {
|
||||
$this->finderPluginId = FinderHelper::getFinderPluginId();
|
||||
}
|
||||
|
||||
// Configure the toolbar.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_finder');
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_INDEX_TOOLBAR_TITLE'), 'search-plus finder');
|
||||
|
||||
if (JDEBUG) {
|
||||
$dropdown = $toolbar->dropdownButton('indexing-group');
|
||||
$dropdown->text('COM_FINDER_INDEX')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-archive')
|
||||
->buttonClass('btn btn-action');
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->popupButton('index', 'COM_FINDER_INDEX')
|
||||
->popupType('iframe')
|
||||
->textHeader(Text::_('COM_FINDER_HEADING_INDEXER'))
|
||||
->url('index.php?option=com_finder&view=indexer&tmpl=component')
|
||||
->modalWidth('800px')
|
||||
->modalHeight('400px')
|
||||
->icon('icon-archive')
|
||||
->title(Text::_('COM_FINDER_HEADING_INDEXER'));
|
||||
|
||||
$childBar->linkButton('indexdebug', 'COM_FINDER_INDEX_TOOLBAR_INDEX_DEBUGGING')
|
||||
->url('index.php?option=com_finder&view=indexer&layout=debug')
|
||||
->icon('icon-tools');
|
||||
} else {
|
||||
$toolbar->popupButton('index', 'COM_FINDER_INDEX')
|
||||
->popupType('iframe')
|
||||
->textHeader(Text::_('COM_FINDER_HEADING_INDEXER'))
|
||||
->url('index.php?option=com_finder&view=indexer&tmpl=component')
|
||||
->modalWidth('800px')
|
||||
->modalHeight('400px')
|
||||
->icon('icon-archive')
|
||||
->title(Text::_('COM_FINDER_HEADING_INDEXER'));
|
||||
}
|
||||
|
||||
|
||||
if (!$this->isEmptyState) {
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
$dropdown = $toolbar->dropdownButton('status-group')
|
||||
->text('JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('index.publish')->listCheck(true);
|
||||
$childBar->unpublish('index.unpublish')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.delete')) {
|
||||
$toolbar->confirmButton('delete', 'JTOOLBAR_DELETE', 'index.delete')
|
||||
->message('COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT')
|
||||
->icon('icon-delete')
|
||||
->listCheck(true);
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('maintenance-group', 'COM_FINDER_INDEX_TOOLBAR_MAINTENANCE')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-wrench')
|
||||
->buttonClass('btn btn-action');
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->standardButton('cog', 'COM_FINDER_INDEX_TOOLBAR_OPTIMISE', 'index.optimise');
|
||||
$childBar->confirmButton('index-purge', 'COM_FINDER_INDEX_TOOLBAR_PURGE', 'index.purge')
|
||||
->message('COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT')
|
||||
->icon('icon-trash');
|
||||
}
|
||||
|
||||
$toolbar->popupButton('statistics', 'COM_FINDER_STATISTICS')
|
||||
->popupType('iframe')
|
||||
->textHeader(Text::_('COM_FINDER_STATISTICS_TITLE'))
|
||||
->url('index.php?option=com_finder&view=statistics&tmpl=component')
|
||||
->modalWidth('800px')
|
||||
->modalHeight('500px')
|
||||
->title(Text::_('COM_FINDER_STATISTICS_TITLE'))
|
||||
->icon('icon-bars');
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences('com_finder');
|
||||
}
|
||||
|
||||
$toolbar->help('Smart_Search:_Indexed_Content');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Indexer;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Indexer view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* @var Form $form
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public $form;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
if ($this->getLayout() == 'debug') {
|
||||
$this->form = $this->get('Form');
|
||||
$this->addToolbar();
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
/** @var Toolbar $toolbar */
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_INDEXER_TOOLBAR_TITLE'), 'search-plus finder');
|
||||
|
||||
$toolbar->linkButton('back', 'JTOOLBAR_BACK')
|
||||
->icon('icon-arrow-' . ($this->getLanguage()->isRtl() ? 'right' : 'left'))
|
||||
->url(Route::_('index.php?option=com_finder&view=index'));
|
||||
|
||||
$toolbar->standardButton('index', 'COM_FINDER_INDEX')
|
||||
->icon('icon-play')
|
||||
->onclick('Joomla.debugIndexing();');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Item;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
/**
|
||||
* Index view class for Finder.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The indexed item
|
||||
*
|
||||
* @var object
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* The associated terms
|
||||
*
|
||||
* @var object[]
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $terms;
|
||||
|
||||
/**
|
||||
* The associated taxonomies
|
||||
*
|
||||
* @var object[]
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $taxonomies;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->item = $this->get('Item');
|
||||
$this->terms = $this->get('Terms');
|
||||
$this->taxonomies = $this->get('Taxonomies');
|
||||
|
||||
// Configure the toolbar.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
/** @var Toolbar $toolbar */
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_INDEX_TOOLBAR_TITLE'), 'search-plus finder');
|
||||
|
||||
$toolbar->linkButton('back', 'JTOOLBAR_BACK')
|
||||
->icon('icon-arrow-' . ($this->getLanguage()->isRtl() ? 'right' : 'left'))
|
||||
->url(Route::_('index.php?option=com_finder&view=index'));
|
||||
}
|
||||
}
|
||||
184
administrator/components/com_finder/src/View/Maps/HtmlView.php
Normal file
184
administrator/components/com_finder/src/View/Maps/HtmlView.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Maps;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Groups view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The total number of items
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $total;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Load plugin language files.
|
||||
LanguageHelper::loadPluginLanguage();
|
||||
|
||||
// Load the view data.
|
||||
$this->items = $this->get('Items');
|
||||
$this->total = $this->get('Total');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
if ($this->total === 0 && $this->isEmptyState = $this->get('isEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Prepare the view.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to configure the toolbar for this view.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_finder');
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_MAPS_TOOLBAR_TITLE'), 'search-plus finder');
|
||||
|
||||
if (!$this->isEmptyState) {
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('maps.publish')->listCheck(true);
|
||||
$childBar->unpublish('maps.unpublish')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.delete')) {
|
||||
$toolbar->standardButton('delete', 'JTOOLBAR_DELETE', 'maps.delete')
|
||||
->listCheck(true);
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
$toolbar->popupButton('bars', 'COM_FINDER_STATISTICS')
|
||||
->popupType('iframe')
|
||||
->textHeader(Text::_('COM_FINDER_STATISTICS_TITLE'))
|
||||
->url('index.php?option=com_finder&view=statistics&tmpl=component')
|
||||
->modalWidth('800px')
|
||||
->modalHeight('500px')
|
||||
->title(Text::_('COM_FINDER_STATISTICS_TITLE'))
|
||||
->icon('icon-bars');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences('com_finder');
|
||||
}
|
||||
|
||||
$toolbar->help('Smart_Search:_Content_Maps');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Searches;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View class for a list of search terms.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* True if gathering search statistics is enabled
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $enabled;
|
||||
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* The actions the user is authorised to perform
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $canDo;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->state = $this->get('State');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
$this->enabled = $this->state->params->get('gather_search_statistics', 0);
|
||||
$this->canDo = ContentHelper::getActions('com_finder');
|
||||
$uri = Uri::getInstance();
|
||||
$link = 'index.php?option=com_config&view=component&component=com_finder&return=' . base64_encode($uri);
|
||||
$output = HTMLHelper::_('link', Route::_($link), Text::_('JOPTIONS'));
|
||||
|
||||
if (!\count($this->items) && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Check if component is enabled
|
||||
if (!$this->enabled) {
|
||||
// Check if the user has access to the component options
|
||||
if ($this->canDo->get('core.admin') || $this->canDo->get('core.options')) {
|
||||
$app->enqueueMessage(Text::sprintf('COM_FINDER_LOGGING_DISABLED', $output), 'warning');
|
||||
} else {
|
||||
$app->enqueueMessage(Text::_('COM_FINDER_LOGGING_DISABLED_NO_AUTH'), 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the view.
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = $this->canDo;
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_FINDER_MANAGER_SEARCHES'), 'search');
|
||||
|
||||
if (!$this->isEmptyState) {
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
$toolbar->standardButton('reset', 'JSEARCH_RESET', 'searches.reset')
|
||||
->icon('icon-refresh')
|
||||
->listCheck(false);
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences('com_finder');
|
||||
}
|
||||
|
||||
$toolbar->help('Smart_Search:_Search_Term_Analysis');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Finder\Administrator\View\Statistics;
|
||||
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Statistics view class for Finder.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The index statistics
|
||||
*
|
||||
* @var \Joomla\CMS\Object\CMSObject
|
||||
*
|
||||
* @since 3.6.1
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Method to display the view.
|
||||
*
|
||||
* @param string $tpl A template file to load. [optional]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Load the view data.
|
||||
$this->data = $this->get('Data');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
}
|
||||
92
administrator/components/com_finder/tmpl/filter/edit.php
Normal file
92
administrator/components/com_finder/tmpl/filter/edit.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
Text::script('COM_FINDER_FILTER_SHOW_ALL', true);
|
||||
Text::script('COM_FINDER_FILTER_HIDE_ALL', true);
|
||||
|
||||
$this->ignore_fieldsets = ['jbasic'];
|
||||
|
||||
$this->useCoreUI = true;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate')
|
||||
->useScript('com_finder.finder-edit');
|
||||
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&view=filter&layout=edit&filter_id=' . (int) $this->item->filter_id); ?>" method="post" name="adminForm" id="adminForm" aria-label="<?php echo Text::_('COM_FINDER_FILTER_FORM_TITLE_' . ((int) $this->item->filter_id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
|
||||
|
||||
<div class="main-card">
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'details', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'details', Text::_('COM_FINDER_EDIT_FILTER')); ?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<?php if ($this->total > 0) : ?>
|
||||
<div class="well">
|
||||
<?php echo $this->form->renderField('map_count'); ?>
|
||||
</div>
|
||||
<button class="btn btn-secondary filter-toggle-all" type="button">
|
||||
<span class="icon-square" aria-hidden="true"></span> <?php echo Text::_('JGLOBAL_SELECTION_INVERT'); ?></button>
|
||||
|
||||
<button class="btn btn-secondary float-end" type="button" id="expandAccordion"><?php echo Text::_('COM_FINDER_FILTER_SHOW_ALL'); ?></button>
|
||||
<hr>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('filter.slider', ['selected_nodes' => $this->filter->data]); ?>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<?php echo LayoutHelper::render('joomla.edit.global', $this); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'publishing', Text::_('JGLOBAL_FIELDSET_OPTIONS')); ?>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<fieldset id="fieldset-publishingdata" class="options-form">
|
||||
<legend><?php echo Text::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></legend>
|
||||
<div>
|
||||
<?php echo LayoutHelper::render('joomla.edit.publishingdata', $this); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<fieldset id="fieldset-filter" class="options-form">
|
||||
<legend><?php echo Text::_('COM_FINDER_FILTER_FIELDSET_PARAMS'); ?></legend>
|
||||
<div>
|
||||
<?php echo $this->form->renderFieldset('jbasic'); ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.params', $this); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="return" value="<?php echo Factory::getApplication()->getInput()->get('return', '', 'BASE64'); ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</form>
|
||||
131
administrator/components/com_finder/tmpl/filters/default.php
Normal file
131
administrator/components/com_finder/tmpl/filters/default.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->get('id');
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
|
||||
Text::script('COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT');
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('com_finder.filters')
|
||||
->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&view=filters'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_FINDER_NO_RESULTS_OR_FILTERS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_FILTERS_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_BY', 'a.created_by_alias', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_ON', 'a.created', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_MAP_COUNT', 'a.map_count', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.filter_id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$canCreate = $user->authorise('core.create', 'com_finder');
|
||||
$canEdit = $user->authorise('core.edit', 'com_finder');
|
||||
$userAuthoriseCoreManage = $user->authorise('core.manage', 'com_checkin');
|
||||
$userAuthoriseCoreEditState = $user->authorise('core.edit.state', 'com_finder');
|
||||
$userId = $user->id;
|
||||
foreach ($this->items as $i => $item) :
|
||||
$canCheckIn = $userAuthoriseCoreManage || $item->checked_out == $userId || is_null($item->checked_out);
|
||||
$canChange = $userAuthoriseCoreEditState && $canCheckIn;
|
||||
$escapedTitle = $this->escape($item->title);
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->filter_id, false, 'cid', 'cb', $item->title); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->state, $i, 'filters.', $canChange); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'filters.', $canCheckIn); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_finder&task=filter.edit&filter_id=' . (int) $item->filter_id); ?>">
|
||||
<?php echo $escapedTitle; ?></a>
|
||||
<?php else : ?>
|
||||
<?php echo $escapedTitle; ?>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->created_by_alias ?: $item->user_name; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('date', $item->created, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->map_count; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo (int) $item->filter_id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_FINDER_FILTERS_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_FINDER_FILTERS_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_FINDER',
|
||||
'formURL' => 'index.php?option=com_finder&view=filters',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Smart_Search_quickstart_guide',
|
||||
'icon' => 'icon-search-plus finder',
|
||||
'btnadd' => Text::_('COM_FINDER_FILTERS_EMPTYSTATE_BUTTON_ADD'),
|
||||
'content' => Text::_('COM_FINDER_FILTERS_EMPTYSTATE_CONTENT'),
|
||||
'title' => Text::_('COM_FINDER_FILTERS_TOOLBAR_TITLE'),
|
||||
];
|
||||
|
||||
if ($this->getCurrentUser()->authorise('core.create', 'com_finder')) {
|
||||
$displayData['createURL'] = "index.php?option=com_finder&task=filter.add";
|
||||
}
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
169
administrator/components/com_finder/tmpl/index/default.php
Normal file
169
administrator/components/com_finder/tmpl/index/default.php
Normal file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
$lang = $this->getLanguage();
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('multiselect')
|
||||
->useScript('table.columns');
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&view=index'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if ($this->finderPluginId) : ?>
|
||||
<?php $link = Route::_('index.php?option=com_plugins&client_id=0&task=plugin.edit&extension_id=' . $this->finderPluginId . '&tmpl=component&layout=modal'); ?>
|
||||
<?php echo HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'plugin' . $this->finderPluginId . 'Modal',
|
||||
[
|
||||
'url' => $link,
|
||||
'title' => Text::_('COM_FINDER_EDIT_PLUGIN_SETTINGS'),
|
||||
'height' => '400px',
|
||||
'width' => '800px',
|
||||
'bodyHeight' => '70',
|
||||
'modalWidth' => '80',
|
||||
'closeButton' => false,
|
||||
'backdrop' => 'static',
|
||||
'keyboard' => false,
|
||||
'footer' => '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"'
|
||||
. ' onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#closeBtn\'})">'
|
||||
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
|
||||
. '<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#saveBtn\'})">'
|
||||
. Text::_("JSAVE") . '</button>'
|
||||
. '<button type="button" class="btn btn-success" onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#applyBtn\'}); return false;">'
|
||||
. Text::_("JAPPLY") . '</button>'
|
||||
]
|
||||
); ?>
|
||||
<?php endif; ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_INDEX_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'l.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'l.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_INDEX_TYPE', 't.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_INDEX_DATE', 'l.indexdate', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<th scope="col" class="w-10 nowrap d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'l.language', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<th scope="col" class="w-15 d-none d-md-table-cell text-center">
|
||||
<?php echo Text::_('COM_FINDER_INDEX_HEADING_DETAILS'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-30 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_INDEX_HEADING_LINK_URL', 'l.url', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $canChange = $this->getCurrentUser()->authorise('core.manage', 'com_finder'); ?>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->link_id, false, 'cid', 'cb', $item->title); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'index.', $canChange, 'cb'); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if (JDEBUG) : ?>
|
||||
<a href="index.php?option=com_finder&view=item&id=<?php echo $item->link_id; ?>">
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape($item->title); ?>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php
|
||||
$key = LanguageHelper::branchSingular($item->t_title);
|
||||
echo $lang->hasKey($key) ? Text::_($key) : $item->t_title;
|
||||
?>
|
||||
</td>
|
||||
<td class="small d-none d-md-table-cell text-center">
|
||||
<?php echo HTMLHelper::_('date', $item->indexdate, Text::_('DATE_FORMAT_LC4')); ?>
|
||||
</td>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo LayoutHelper::render('joomla.content.language', $item); ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="text-center d-none d-md-table-cell text-center">
|
||||
<?php if ((int) $item->publish_start_date or (int) $item->publish_end_date or (int) $item->start_date or (int) $item->end_date) : ?>
|
||||
<span tabindex="0">
|
||||
<span class="icon-calendar" aria-hidden="true"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('COM_FINDER_INDEX_DATE_INFO_TITLE'); ?></span>
|
||||
</span>
|
||||
<div role="tooltip" id="tip<?php echo $i; ?>">
|
||||
<?php
|
||||
$publishStartDate = $item->publish_start_date !== null ? HTMLHelper::_('date', $item->publish_start_date, Text::_('DATE_FORMAT_LC5'), 'UTC') : '';
|
||||
$publishEndDate = $item->publish_end_date !== null ? HTMLHelper::_('date', $item->publish_end_date, Text::_('DATE_FORMAT_LC5'), 'UTC') : '';
|
||||
$startDate = $item->start_date !== null ? HTMLHelper::_('date', $item->start_date, Text::_('DATE_FORMAT_LC5'), 'UTC') : '';
|
||||
$endDate = $item->end_date !== null ? HTMLHelper::_('date', $item->end_date, Text::_('DATE_FORMAT_LC5'), 'UTC') : '';
|
||||
?>
|
||||
<?php echo Text::sprintf('COM_FINDER_INDEX_DATE_INFO', $publishStartDate, $publishEndDate, $startDate, $endDate); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="small break-word d-none d-md-table-cell">
|
||||
<?php echo (strlen($item->url) > 80) ? substr($item->url, 0, 70) . '...' : $item->url; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="task" value="display">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_FINDER_INDEX_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_FINDER_INDEX_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_FINDER',
|
||||
'formURL' => 'index.php?option=com_finder&view=index',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Smart_Search_quickstart_guide',
|
||||
'icon' => 'icon-search-plus finder',
|
||||
'content' => Text::_('COM_FINDER_INDEX_NO_DATA') . '<br>' . Text::_('COM_FINDER_INDEX_TIP'),
|
||||
'title' => Text::_('COM_FINDER_HEADING_INDEXER'),
|
||||
'createURL' => "javascript:document.getElementsByClassName('button-index')[0].click();",
|
||||
];
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
|
||||
if ($this->finderPluginId) : ?>
|
||||
<?php $link = Route::_('index.php?option=com_plugins&client_id=0&task=plugin.edit&extension_id=' . $this->finderPluginId . '&tmpl=component&layout=modal'); ?>
|
||||
<?php echo HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'plugin' . $this->finderPluginId . 'Modal',
|
||||
[
|
||||
'url' => $link,
|
||||
'title' => Text::_('COM_FINDER_EDIT_PLUGIN_SETTINGS'),
|
||||
'height' => '400px',
|
||||
'width' => '800px',
|
||||
'bodyHeight' => '70',
|
||||
'modalWidth' => '80',
|
||||
'closeButton' => false,
|
||||
'backdrop' => 'static',
|
||||
'keyboard' => false,
|
||||
'footer' => '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"'
|
||||
. ' onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#closeBtn\'})">'
|
||||
. Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
|
||||
. '<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#saveBtn\'})">'
|
||||
. Text::_("JSAVE") . '</button>'
|
||||
. '<button type="button" class="btn btn-success" onclick="Joomla.iframeButtonClick({iframeSelector: \'#plugin' . $this->finderPluginId . 'Modal\', buttonSelector: \'#applyBtn\'}); return false;">'
|
||||
. Text::_("JAPPLY") . '</button>'
|
||||
]
|
||||
); ?>
|
||||
<?php endif;
|
||||
61
administrator/components/com_finder/tmpl/indexer/debug.php
Normal file
61
administrator/components/com_finder/tmpl/indexer/debug.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var Joomla\Component\Finder\Administrator\View\Indexer\HtmlView $this */
|
||||
|
||||
Text::script('COM_FINDER_INDEXER_MESSAGE_COMPLETE', true);
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('com_finder.debug');
|
||||
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&layout=debug'); ?>" method="post" name="adminForm" id="debug-form">
|
||||
<div class="form-horizontal">
|
||||
<div class="card mt-3">
|
||||
<div class="card-body">
|
||||
<fieldset class="adminform p-4">
|
||||
<div class="alert alert-info">
|
||||
<h2 class="alert-heading"><?php echo Text::_('COM_FINDER_INDEXER_MSG_DEBUGGING_INDEXING'); ?></h2>
|
||||
<?php echo Text::_('COM_FINDER_INDEXER_MSG_DEBUGGING_INDEXING_TEXT'); ?>
|
||||
</div>
|
||||
<?php echo $this->form->renderField('plugin'); ?>
|
||||
<?php echo $this->form->renderField('id'); ?>
|
||||
|
||||
<input id="finder-indexer-token" type="hidden" name="<?php echo Factory::getSession()->getFormToken(); ?>" value="1">
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="card mt-3">
|
||||
<div class="card-body">
|
||||
<fieldset class="adminform">
|
||||
<legend><?php echo Text::_('COM_FINDER_INDEXER_OUTPUT_AREA_TITLE'); ?></legend>
|
||||
<div id="indexer-output" class="border p-3" style="min-height:200px;">
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
41
administrator/components/com_finder/tmpl/indexer/default.php
Normal file
41
administrator/components/com_finder/tmpl/indexer/default.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
Text::script('COM_FINDER_INDEXER_MESSAGE_COMPLETE');
|
||||
Text::script('COM_FINDER_AN_ERROR_HAS_OCCURRED');
|
||||
Text::script('COM_FINDER_MESSAGE_RETURNED');
|
||||
Text::script('JLIB_JS_AJAX_ERROR_OTHER');
|
||||
Text::script('JLIB_JS_AJAX_ERROR_PARSE');
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useStyle('com_finder.indexer')
|
||||
->useScript('com_finder.indexer');
|
||||
|
||||
?>
|
||||
|
||||
<div class="text-center">
|
||||
<h1 id="finder-progress-header" class="m-t-2" aria-live="assertive"><?php echo Text::_('COM_FINDER_INDEXER_HEADER_INIT'); ?></h1>
|
||||
<p id="finder-progress-message" aria-live="polite"><?php echo Text::_('COM_FINDER_INDEXER_MESSAGE_INIT'); ?></p>
|
||||
<div id="progress" class="progress">
|
||||
<div id="progress-bar" class="progress-bar bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<?php if (JDEBUG) : ?>
|
||||
<dl id="finder-debug-data" class="row">
|
||||
</dl>
|
||||
<?php endif; ?>
|
||||
<input id="finder-indexer-token" type="hidden" name="<?php echo Factory::getSession()->getFormToken(); ?>" value="1">
|
||||
</div>
|
||||
100
administrator/components/com_finder/tmpl/item/default.php
Normal file
100
administrator/components/com_finder/tmpl/item/default.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
?>
|
||||
<div role="main">
|
||||
<h1 class="mb-3"><?php echo $this->item->title; ?></h1>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><h2><?php echo Text::_('COM_FINDER_ITEM_FIELDSET_ITEM_TITLE'); ?></h2></div>
|
||||
<div class="card-body">
|
||||
<dl class="row">
|
||||
<?php foreach ($this->item as $key => $value) : ?>
|
||||
<dt class="col-sm-3"><?php echo $key; ?></dt>
|
||||
<dd class="col-sm-9<?php echo $key == 'object' ? ' text-break' : '';?>"><?php echo $value; ?></dd>
|
||||
<?php endforeach; ?>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><h2><?php echo Text::_('COM_FINDER_ITEM_FIELDSET_TERMS_TITLE'); ?></h2></div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_ITEM_TERMS_TABLE_CAPTION'); ?>,
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">id</th>
|
||||
<th scope="col">term</th>
|
||||
<th scope="col">stem</th>
|
||||
<th scope="col">common</th>
|
||||
<th scope="col">phrase</th>
|
||||
<th scope="col">weight</th>
|
||||
<th scope="col">links</th>
|
||||
<th scope="col">language</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->terms as $term) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo $term->term_id; ?></th>
|
||||
<td><?php echo $term->term; ?></td>
|
||||
<td><?php echo $term->stem; ?></td>
|
||||
<td><?php echo $term->common; ?></td>
|
||||
<td><?php echo $term->phrase; ?></td>
|
||||
<td><?php echo $term->weight; ?></td>
|
||||
<td><?php echo $term->links; ?></td>
|
||||
<td><?php echo $term->language; ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><h2><?php echo Text::_('COM_FINDER_ITEM_FIELDSET_TAXONOMIES_TITLE'); ?></h2></div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_ITEM_TAXONOMIES_TABLE_CAPTION'); ?>,
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">id</th>
|
||||
<th scope="col">title</th>
|
||||
<th scope="col">alias</th>
|
||||
<th scope="col">lft</th>
|
||||
<th scope="col">path</th>
|
||||
<th scope="col">state</th>
|
||||
<th scope="col">access</th>
|
||||
<th scope="col">language</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->taxonomies as $taxonomy) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo $taxonomy->id; ?></th>
|
||||
<td><?php echo $taxonomy->title; ?></td>
|
||||
<td><?php echo $taxonomy->alias; ?></td>
|
||||
<td><?php echo $taxonomy->lft; ?></td>
|
||||
<td><?php echo $taxonomy->path; ?></td>
|
||||
<td><?php echo $taxonomy->state; ?></td>
|
||||
<td><?php echo $taxonomy->access; ?></td>
|
||||
<td><?php echo $taxonomy->language; ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
174
administrator/components/com_finder/tmpl/maps/default.php
Normal file
174
administrator/components/com_finder/tmpl/maps/default.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Multilanguage;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Finder\Administrator\Helper\LanguageHelper;
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
$lang = Factory::getLanguage();
|
||||
$branchFilter = $this->escape($this->state->get('filter.branch'));
|
||||
|
||||
Text::script('COM_FINDER_MAPS_CONFIRM_DELETE_PROMPT');
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('com_finder.maps')
|
||||
->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&view=maps'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_FINDER_MAPS_NO_CONTENT'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_MAPS_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'branch_title, a.lft', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php if (!$branchFilter) : ?>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo Text::_('COM_FINDER_HEADING_CHILDREN'); ?>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<span class="icon-check" aria-hidden="true"></span>
|
||||
<span class="d-none d-md-inline"><?php echo Text::_('COM_FINDER_MAPS_COUNT_PUBLISHED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<span class="icon-times" aria-hidden="true"></span>
|
||||
<span class="d-none d-md-inline"><?php echo Text::_('COM_FINDER_MAPS_COUNT_UNPUBLISHED_ITEMS'); ?></span>
|
||||
</th>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<th scope="col" class="w-10 nowrap d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'a.language', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $canChange = $this->getCurrentUser()->authorise('core.manage', 'com_finder'); ?>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->id, false, 'cid', 'cb', $item->title); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->state, $i, 'maps.', $canChange, 'cb'); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php
|
||||
if (trim($item->branch_title, '*') === 'Language') {
|
||||
$title = LanguageHelper::branchLanguageTitle($item->title);
|
||||
} else {
|
||||
$key = LanguageHelper::branchSingular($item->title);
|
||||
$title = $lang->hasKey($key) ? Text::_($key) : $item->title;
|
||||
}
|
||||
?>
|
||||
<?php echo str_repeat('<span class="gi">—</span>', $item->level - 1); ?>
|
||||
<?php echo $this->escape($title); ?>
|
||||
<?php if ($this->escape(trim($title, '*')) === 'Language' && Multilanguage::isEnabled()) : ?>
|
||||
<div class="small">
|
||||
<strong><?php echo Text::_('COM_FINDER_MAPS_MULTILANG'); ?></strong>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<?php if (!$branchFilter) : ?>
|
||||
<td class="text-center btns itemnumber">
|
||||
<?php if ($item->rgt - $item->lft > 1) : ?>
|
||||
<a href="<?php echo Route::_('index.php?option=com_finder&view=maps&filter[branch]=' . $item->id); ?>"
|
||||
aria-describedby="tip-map<?php echo $i; ?>">
|
||||
<span class="btn btn-info"><?php echo floor(($item->rgt - $item->lft) / 2); ?></span>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-map<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_FINDER_HEADING_CHILDREN'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td class="text-center btns itemnumber">
|
||||
<?php if ($item->level > 1) : ?>
|
||||
<a class="btn <?php echo ((int) $item->count_published > 0) ? 'btn-success' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=com_finder&view=index&filter[state]=1&filter[content_map]=' . $item->id); ?>"
|
||||
aria-describedby="tip-publish<?php echo $i; ?>">
|
||||
<?php echo (int) $item->count_published; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-publish<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_FINDER_MAPS_COUNT_PUBLISHED_ITEMS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center btns itemnumber">
|
||||
<?php if ($item->level > 1) : ?>
|
||||
<a class="btn <?php echo ((int) $item->count_unpublished > 0) ? 'btn-danger' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=com_finder&view=index&filter[state]=0&filter[content_map]=' . $item->id); ?>"
|
||||
aria-describedby="tip-unpublish<?php echo $i; ?>">
|
||||
<?php echo (int) $item->count_unpublished; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-unpublish<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_FINDER_MAPS_COUNT_UNPUBLISHED_ITEMS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
-
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<?php if (Multilanguage::isEnabled()) : ?>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<?php echo $item->language; ?>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="task" value="display">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_FINDER_MAPS_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_FINDER_MAPS_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
24
administrator/components/com_finder/tmpl/maps/emptystate.php
Normal file
24
administrator/components/com_finder/tmpl/maps/emptystate.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_FINDER',
|
||||
'formURL' => 'index.php?option=com_finder&view=maps',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help4.x:Smart_Search:_Content_Maps',
|
||||
'icon' => 'icon-search-plus finder',
|
||||
'title' => Text::_('COM_FINDER_MAPS_TOOLBAR_TITLE')
|
||||
];
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('multiselect');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_finder&view=searches'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this, 'options' => ['filterButton' => false]]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_FINDER_SEARCHES_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_PHRASE', 'a.searchterm', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-15">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_HITS', 'a.hits', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo Text::_('COM_FINDER_HEADING_RESULTS'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<th scope="row" class="break-word">
|
||||
<?php echo $this->escape($item->searchterm); ?>
|
||||
</th>
|
||||
<td>
|
||||
<?php echo (int) $item->hits; ?>
|
||||
</td>
|
||||
<td class="text-center btns">
|
||||
<?php echo (int) $item->results; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_FINDER_SEARCH_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_FINDER_SEARCH_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_FINDER',
|
||||
'formURL' => 'index.php?option=com_finder&view=searches',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help4.x:Smart_Search:_Search_Term_Analysis',
|
||||
'icon' => 'icon-search',
|
||||
'title' => Text::_('COM_FINDER_MANAGER_SEARCHES'),
|
||||
'content' => Text::_('COM_FINDER_EMPTYSTATE_SEARCHES_CONTENT'),
|
||||
];
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_finder
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
?>
|
||||
<div class="container-popup">
|
||||
<table class="table table-sm">
|
||||
<caption class="caption-top"><?php echo Text::sprintf('COM_FINDER_STATISTICS_STATS_DESCRIPTION', number_format($this->data->term_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR')), number_format($this->data->link_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR')), number_format($this->data->taxonomy_node_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR')), number_format($this->data->taxonomy_branch_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR'))); ?></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
<?php echo Text::_('COM_FINDER_STATISTICS_LINK_TYPE_HEADING'); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo Text::_('COM_FINDER_STATISTICS_LINK_TYPE_COUNT'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->data->type_list as $type) : ?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<?php
|
||||
$lang_key = 'PLG_FINDER_STATISTICS_' . str_replace(' ', '_', $type->type_title);
|
||||
$lang_string = Text::_($lang_key);
|
||||
echo $lang_string === $lang_key ? $type->type_title : $lang_string;
|
||||
?>
|
||||
</th>
|
||||
<td>
|
||||
<span class="badge bg-info"><?php echo number_format($type->link_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR')); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong><?php echo Text::_('COM_FINDER_STATISTICS_LINK_TYPE_TOTAL'); ?></strong>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-info"><?php echo number_format($this->data->link_count, 0, Text::_('DECIMALS_SEPARATOR'), Text::_('THOUSANDS_SEPARATOR')); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_FINDER_STATS_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_FINDER_STATS_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
Reference in New Issue
Block a user