This commit is contained in:
2024-12-31 11:07:09 +01:00
parent df7915205d
commit e089172b15
1916 changed files with 165422 additions and 271 deletions

View File

@ -0,0 +1,461 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use NRFramework\Conditions\Conditions\Component\ContentBase;
use Joomla\CMS\Language\Text;
use Joomla\Registry\Registry;
use Joomla\CMS\Factory;
use NRFramework\Cache;
JLoader::register('ACF_Field', JPATH_PLUGINS . '/system/acf/helper/plugin.php');
if (!class_exists('ACF_Field'))
{
Factory::getApplication()->enqueueMessage('Advanced Custom Fields System Plugin is missing', 'error');
return;
}
class PlgFieldsACFArticles extends ACF_Field
{
/**
* Update the label of the field in filters.
*
* @param \Bluecoder\Component\Jfilters\Administrator\Model\Filter\Option\Collection $options
*
* @return \Bluecoder\Component\Jfilters\Administrator\Model\Filter\Option\Collection
*/
public function onJFiltersOptionsAfterCreation(\Bluecoder\Component\Jfilters\Administrator\Model\Filter\Option\Collection $options)
{
// Make sure it is a field of that type
if ($options->getFilterItem()->getAttributes()->get('type') !== $this->_name)
{
return $options;
}
$contentAssignment = new ContentBase();
foreach ($options as $option)
{
if (!$article = $contentAssignment->getItem($option->getLabel()))
{
continue;
}
$option->setLabel($article->title);
}
return $options;
}
public function onContentBeforeSave($context, $item, $isNew, $data = [])
{
if (!is_array($data))
{
return true;
}
if (!isset($data['com_fields']))
{
return true;
}
// Create correct context for category
if ($context == 'com_categories.category')
{
$context = $item->get('extension') . '.categories';
}
// Load Fields Component Helper class
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
// Check the context
$parts = FieldsHelper::extract($context, $item);
if (!$parts)
{
return true;
}
// Compile the right context for the fields
$context = $parts[0] . '.' . $parts[1];
// Loading the fields
$fields = FieldsHelper::getFields($context, $item);
if (!$fields)
{
return true;
}
// Get the fields data
$fieldsData = !empty($data['com_fields']) ? $data['com_fields'] : [];
// Whether we should clean up the temp folder at the end of this process
$should_clean = false;
// Get the Fields Model
if (!defined('nrJ4'))
{
$model = JModelLegacy::getInstance('Field', 'FieldsModel', ['ignore_request' => true]);
}
else
{
$model = Factory::getApplication()->bootComponent('com_fields')->getMVCFactory()->createModel('Field', 'Administrator', ['ignore_request' => true]);
}
// Cache subform fields
$subform_fields = [];
$error = false;
// Loop over the fields
foreach ($fields as $field)
{
$field_type = $field->type;
/**
* Check whether a Gallery field is used within the Subform field.
*/
if ($field_type === 'subform')
{
// Ensure it has a value
if (!$subform_value = json_decode($field->value, true))
{
continue;
}
foreach ($subform_value as $key => $value)
{
if (!is_array($value))
{
continue;
}
foreach ($value as $_key => $_value)
{
// Get Field ID
$field_id = str_replace('field', '', $_key);
// Get Field by ID
$subform_field = isset($subform_fields[$field_id]) ? $subform_fields[$field_id] : $model->getItem($field_id);
// Only proceed for this field type
if ($subform_field->type !== $this->_name)
{
continue;
}
// Cache field
if (!isset($subform_fields[$field_id]))
{
$subform_fields[$field_id] = $subform_field;
}
$check_value = isset($fieldsData[$field->name][$key][$_key]) ? $fieldsData[$field->name][$key][$_key] : false;
if (!$check_value)
{
break;
}
$fieldParams = new Registry($subform_field->fieldparams);
$check_value = is_array($check_value) ? $check_value : [$check_value];
if ($min_articles = (int) $fieldParams->get('min_articles', 0))
{
if (count($check_value) < $min_articles)
{
Factory::getApplication()->enqueueMessage(sprintf(Text::_('ACF_ARTICLES_MIN_ITEMS_REQUIRED'), $subform_field->title, $min_articles), 'error');
$error = true;
break;
}
}
if ($max_articles = (int) $fieldParams->get('max_articles', 0))
{
if (count($check_value) > $max_articles)
{
Factory::getApplication()->enqueueMessage(sprintf(Text::_('ACF_ARTICLES_MAX_ITEMS_REQUIRED'), $subform_field->title, $max_articles), 'error');
$error = true;
break;
}
}
}
}
}
else
{
// Only proceed for this field type
if ($field_type !== $this->_name)
{
continue;
}
// Determine the value if it is available from the data
$value = array_key_exists($field->name, $fieldsData) ? $fieldsData[$field->name] : null;
if (!$value)
{
continue;
}
$value = is_array($value) ? $value : [$value];
if ($min_articles = (int) $field->fieldparams->get('min_articles', 0))
{
if (count($value) < $min_articles)
{
Factory::getApplication()->enqueueMessage(sprintf(Text::_('ACF_ARTICLES_MIN_ITEMS_REQUIRED'), $field->title, $min_articles), 'error');
$error = true;
break;
}
}
if ($max_articles = (int) $field->fieldparams->get('max_articles', 0))
{
if (count($value) > $max_articles)
{
Factory::getApplication()->enqueueMessage(sprintf(Text::_('ACF_ARTICLES_MAX_ITEMS_REQUIRED'), $field->title, $max_articles), 'error');
$error = true;
break;
}
}
}
}
return !$error;
}
/**
* Transforms the field into a DOM XML element and appends it as a child on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param Form $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, Joomla\CMS\Form\Form $form)
{
if (!$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form))
{
return $fieldNode;
}
$field_type = $field->fieldparams->get('articles_type', 'default');
$fieldNode->setAttribute('multiple', true);
$max_articles = (int) $field->fieldparams->get('max_articles', 0);
if ($max_articles === 1)
{
$fieldNode->setAttribute('multiple', false);
}
// Linked
if ($field_type === 'linked')
{
$fieldNode->setAttribute('multiple', false);
$fieldNode->setAttribute('type', 'NRToggle');
// Default state
$fieldNode->setAttribute('default', 'false');
// Checked if Default Value = 1/true
if (isset($field->value) && in_array($field->value, ['1', 'true']))
{
$fieldNode->setAttribute('checked', 'true');
}
}
return $fieldNode;
}
/**
* Prepares the field value for the (front-end) layout
*
* @param string $context The context.
* @param stdclass $item The item.
* @param stdclass $field The field.
*
* @return string
*/
public function onCustomFieldsPrepareField($context, $item, $field)
{
// Check if the field should be processed by us
if (!$this->isTypeSupported($field->type))
{
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
$value = array_filter((array) $field->value);
$type = $field->fieldparams->get('articles_type', 'default');
// Linked articles
if ($type === 'linked')
{
// Abort if no ACF Articles fields are selected
if (!$acf_articles = array_filter($field->fieldparams->get('articles_fields', [])))
{
$field->value = [];
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
// Proceed only if Field Value = 1/true
if (!in_array($field->value, ['1', 'true']))
{
$field->value = [];
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
$cache_key = 'ACFArticles_' . $item->id . '_' . md5(implode(',', $acf_articles));
if (Cache::has($cache_key))
{
$field->value = Cache::get($cache_key);
}
else
{
// Grab all linked articles
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select('a.*')
->from($db->quoteName('#__fields_values', 'fv'))
->join('LEFT', $db->quoteName('#__content', 'a') . ' ON a.id = fv.item_id')
->where($db->quoteName('fv.field_id') . ' IN (' . implode(',', $acf_articles) . ')')
->where($db->quoteName('fv.value') . ' = ' . $db->q($item->id));
$this->prepareArticles($context, $query, $field, $value, true);
Cache::set($cache_key, $field->value);
}
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
if (!$value)
{
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
$cache_key = 'ACFArticles_Auto_' . $item->id . '_' . md5(implode(',', $value));
if (Cache::has($cache_key))
{
$field->value = Cache::get($cache_key);
}
else
{
// Default articles
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select('a.*')
->from($db->quoteName('#__content', 'a'))
->where($db->quoteName('a.id') . ' IN (' . implode(',', array_map('intval', $value)) . ')');
$this->prepareArticles($context, $query, $field, $value);
Cache::set($cache_key, $field->value);
}
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
/**
* Prepares the articles.
*
* @param string $context
* @param object $query
* @param object $field
* @param array $articles
* @param bool $all_filters
*
* @return void
*/
private function prepareArticles($context, $query, &$field, $articles, $all_filters = true)
{
$db = Factory::getDbo();
// Filter results
require_once 'fields/acfarticlesfilters.php';
$payload = $all_filters ? $field->fieldparams : ['order' => $field->fieldparams->get('order')];
$filters = new ACFArticlesFilters($query, $payload);
$query = $filters->apply();
// Set query
$db->setQuery($query);
// Get articles
if (!$articles = $db->loadAssocList())
{
$field->value = [];
return;
}
// Get and set the articles values
foreach ($articles as &$article)
{
$article['custom_fields'] = $this->fetchCustomFields($article);
}
$field->value = $articles;
}
/**
* Returns an article's custom fields.
*
* @return array
*/
private function fetchCustomFields($article = null)
{
if (!$article)
{
return [];
}
$callback = function() use ($article)
{
\JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
if (!$fields = \FieldsHelper::getFields('com_content.article', $article, false))
{
return [];
}
$fieldsAssoc = [];
foreach ($fields as $field)
{
$fieldsAssoc[$field->name] = $field->value;
}
return $fieldsAssoc;
};
return Cache::memo('ACFArticlesFetchCustomFields' . $article['id'], $callback);
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0" group="fields" method="upgrade">
<name>ACF_ARTICLES</name>
<description>ACF_ARTICLES_DESC</description>
<author>Tassos Marinos</author>
<creationDate>Februray 2023</creationDate>
<copyright>Copyright (C) 2023 Tassos Marinos. All rights reserved.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>info@tassos.gr</authorEmail>
<authorUrl>www.tassos.gr</authorUrl>
<version>1.0</version>
<scriptfile>script.install.php</scriptfile>
<files>
<filename plugin="acfarticles">acfarticles.php</filename>
<filename>script.install.helper.php</filename>
<filename>version.php</filename>
<folder>fields</folder>
<folder>language</folder>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<media folder="media" destination="plg_fields_acfarticles">
<folder>css</folder>
<folder>img</folder>
</media>
</extension>

View File

@ -0,0 +1,125 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
require_once JPATH_PLUGINS . '/system/nrframework/helpers/fieldlist.php';
use Joomla\Registry\Registry;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
class JFormFieldACFArticles extends NRFormFieldList
{
public function getInput()
{
$this->hint = $this->getFieldHint();
return parent::getInput();
}
private function getFieldHint()
{
$hint = (string) $this->element['hint'];
return !empty($hint) ? $hint : Text::_('ACF_ARTICLES_SELECT_ARTICLES');
}
/**
* Method to get a list of options for a list input.
*
* @return array
*/
protected function getOptions()
{
require_once 'acfarticlesfilters.php';
// The layout param in the field XML overrides $this->layout and thus we need to set it again.
$this->layout = 'joomla.form.field.list-fancy-select';
$query = $this->db->getQuery(true)
->select('a.*, c.lft as category_lft, c.title as category_title')
->from($this->db->quoteName('#__content', 'a'))
->join('LEFT', $this->db->quoteName('#__categories', 'c') . ' ON c.id = a.catid');
// Get current item id and exclude it from the list
if ($current_item_id = Factory::getApplication()->input->getInt('id'))
{
$query->where($this->db->quoteName('a.id') . ' != ' . (int) $current_item_id);
}
$field_attributes = (array) $this->element->attributes();
$payload = new Registry($field_attributes['@attributes']);
// Apply filters
$filters = new ACFArticlesFilters($query, $payload);
$query = $filters->apply();
$this->db->setQuery($query);
// Get all articles
if (!$items = $this->db->loadObjectList())
{
return;
}
// Get all dropdown choices
$options = [];
// Add hint to single value field
if ($payload->get('max_articles') == '1')
{
$options[] = HTMLHelper::_('select.option', '', $this->getFieldHint());
}
foreach ($items as $item)
{
$options[] = HTMLHelper::_('select.option', $item->id, $item->title);
}
return $options;
}
/**
* Return all categories child ids.
*
* @param array $categories
*
* @return array
*/
private function getCategoriesChildIds($categories = [])
{
$query = $this->db->getQuery(true)
->select('a.id')
->from($this->db->quoteName('#__categories', 'a'))
->where('a.extension = ' . $this->db->quote('com_content'))
->where('a.published = 1');
$children = [];
while (!empty($categories))
{
$query
->clear('where')
->where($this->db->quoteName('a.parent_id') . ' IN (' . implode(',', $categories) . ')');
$this->db->setQuery($query);
$categories = $this->db->loadColumn();
$children = array_merge($children, $categories);
}
return $children;
}
}

View File

@ -0,0 +1,70 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
require_once JPATH_PLUGINS . '/system/nrframework/helpers/fieldlist.php';
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
class JFormFieldACFArticlesFields extends NRFormFieldList
{
public function getInput()
{
$this->hint = Text::_('ACF_ARTICLES_SELECT_ACF_ARTICLES');
return parent::getInput();
}
/**
* Method to get a list of options for a list input.
*
* @return array
*/
protected function getOptions()
{
// The layout param in the field XML overrides $this->layout and thus we need to set it again.
$this->layout = 'joomla.form.field.list-fancy-select';
$query = $this->db->getQuery(true)
->select('id, label')
->from($this->db->quoteName('#__fields'))
->where('type = ' . $this->db->quote('acfarticles'))
->where('state = 1');
// Get current item id and exclude it from the list
if ($current_item_id = Factory::getApplication()->input->getInt('id'))
{
$query->where($this->db->quoteName('id') . ' != ' . (int) $current_item_id);
}
$this->db->setQuery($query);
// Get all fields
if (!$items = $this->db->loadObjectList())
{
return;
}
// Get all dropdown choices
$options = [];
foreach ($items as $item)
{
$options[] = HTMLHelper::_('select.option', $item->id, $item->label);
}
return $options;
}
}

View File

@ -0,0 +1,223 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2019 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Factory;
class ACFArticlesFilters
{
private $db;
private $query;
private $filters;
public function __construct($query, $filters)
{
$this->db = Factory::getDbo();
$this->query = $query;
$this->filters = $filters;
}
public function apply()
{
$this->applyCategories();
$this->applyTags();
$this->applyAuthor();
$this->applyStatus();
$this->applyOrdering();
$this->applyLimit();
return $this->query;
}
public function applyCategories()
{
if (!isset($this->filters['filters_category_enabled']))
{
return;
}
if (!isset($this->filters['filters_category_value']))
{
return;
}
$categories = $this->filters['filters_category_value'];
$inc_children = isset($this->filters['filters_category_inc_children']) ? (string) $this->filters['filters_category_inc_children'] : false;
if (in_array($inc_children, ['1', '2']))
{
$categories = is_string($categories) ? array_map('trim', explode(',', $categories)) : $categories;
$children_categories = $this->getCategoriesChildIds($categories);
// Also include children categories
if ($inc_children === '1')
{
$categories = array_unique(array_filter(array_merge($categories, $children_categories)));
}
// Use only children categories
else
{
$categories = $children_categories;
}
$categories = implode(',', $categories);
}
$this->query->where($this->db->quoteName('a.catid') . ' IN (' . (is_string($categories) ? $categories : implode(',', $categories)) . ')');
}
public function applyTags()
{
if (!isset($this->filters['filters_tag_enabled']))
{
return;
}
if (!isset($this->filters['filters_tag_value']))
{
return;
}
if ($filtersTagEnabled = (string) $this->filters['filters_tag_enabled'] === '1' && $tags = $this->filters['filters_tag_value'])
{
$this->query
->join('INNER', $this->db->quoteName('#__contentitem_tag_map', 't') . ' ON t.content_item_id = a.id')
->where($this->db->quoteName('t.tag_id') . ' IN (' . (is_string($tags) ? $tags : implode(',', $tags)) . ')')
->group($this->db->quoteName('a.id'));
}
}
public function applyAuthor()
{
if (!isset($this->filters['filters_author_enabled']))
{
return;
}
if (!isset($this->filters['filters_author_value']))
{
return;
}
if ($filtersAuthorEnabled = (string) $this->filters['filters_author_enabled'] === '1' && $authors = $this->filters['filters_author_value'])
{
$this->query->where($this->db->quoteName('a.created_by') . ' IN (' . (is_string($authors) ? $authors : implode(',', $authors)) . ')');
}
}
public function applyStatus()
{
// Default status is to show published articles
$status = [1];
if (isset($this->filters['filters_status_value']) && is_array($this->filters['filters_status_value']) && count($this->filters['filters_status_value']))
{
$status = $this->filters['filters_status_value'];
}
// Set articles status
$this->query->where($this->db->quoteName('a.state') . ' IN (' . (is_string($status) ? $status : implode(',', $status)) . ')');
}
private function applyOrdering()
{
// Apply ordering
if (!$this->filters['order'])
{
return;
}
$order = is_string($this->filters['order']) ? explode(',', $this->filters['order']) : $this->filters['order'];
$order = array_filter(array_map('trim', $order));
$orders = [];
foreach ($order as $item)
{
$lastUnderscorePos = strrpos($item, '_');
$part1 = substr($item, 0, $lastUnderscorePos);
$part2 = substr($item, $lastUnderscorePos + 1);
if (!$part1 || !$part2)
{
break;
}
$orders[] = $part1 . ' ' . $part2;
}
if ($orders)
{
$this->query->order($this->db->escape(implode(',', $orders)));
}
}
private function applyLimit()
{
// Apply limit
$limit = isset($this->filters['limit']) ? (int) $this->filters['limit'] : false;
if (!$limit)
{
return;
}
$this->query->setLimit($limit);
}
/**
* Return all categories child ids.
*
* @param array $categories
*
* @return array
*/
private function getCategoriesChildIds($categories = [])
{
$query = $this->db->getQuery(true)
->select('a.id')
->from($this->db->quoteName('#__categories', 'a'))
->where('a.extension = ' . $this->db->quote('com_content'))
->where('a.published = 1');
$children = [];
while (!empty($categories))
{
$query
->clear('where')
->where($this->db->quoteName('a.parent_id') . ' IN (' . implode(',', $categories) . ')');
$this->db->setQuery($query);
$categories = $this->db->loadColumn();
$children = array_merge($children, $categories);
}
return $children;
}
}

View File

@ -0,0 +1,78 @@
; @package Advanced Custom Fields
; @version 2.8.8 Pro
;
; @author Tassos Marinos - http://www.tassos.gr/joomla-extensions
; @copyright Copyright (c) 2023 Tassos Marinos. All rights reserved.
; @license http://www.tassos.gr
PLG_FIELDS_ACFARTICLES_LABEL="ACF - Articles"
ACF_ARTICLES="Fields - ACF Articles"
ACF_ARTICLES_DESC="Select and connect articles to each other."
ACF_ARTICLES_VALUE_DESC="Select articles to connect to this item."
ACF_ARTICLES_MIN_ARTICLES="Minimum Articles"
ACF_ARTICLES_MIN_ARTICLES_DESC="Sets a limit on the minimum articles that can be selected."
ACF_ARTICLES_MAX_ARTICLES="Maximum Articles"
ACF_ARTICLES_MAX_ARTICLES_DESC="Sets a limit on the maximum articles that can be selected."
ACF_ARTICLES_FILTER_BY_CATEGORY="By Category"
ACF_ARTICLES_FILTER_CATEGORY_DESC="Set whether to filter the articles by categories."
ACF_ARTICLES_FILTER_CATEGORY_SELECTION_DESC="Select categories to filter the articles."
ACF_ARTICLES_FILTER_BY_TAG="By Tag"
ACF_ARTICLES_FILTER_TAG_DESC="Set whether to filter the articles by tags."
ACF_ARTICLES_FILTER_TAG_SELECTION_DESC="Select tags to filter the articles."
ACF_ARTICLES_FILTER_BY_AUTHOR="By Author"
ACF_ARTICLES_FILTER_AUTHOR_DESC="Set whether to filter the articles by authors."
ACF_ARTICLES_FILTER_AUTHOR_SELECTION_DESC="Select authors to filter the articles."
ACF_ARTICLES_LAYOUT_DESC="Select the layout to display the articles."
ACF_ARTICLES_LAYOUT_CUSTOM="Custom Layout"
ACF_ARTICLES_LAYOUT_CUSTOM_DESC="Enter HTML code for each article item. Smart Tags are also supported.<br /><br />To access an article's data, use the Smart Tag {acf.article.KEY} where KEY is the article object key.<br/><br/>Helpful Smart Tags:</br>{acf.article.link}: The Article URL<br />{acf.article.introtext}: The Article intro text<br />{acf.article.images.image_intro}: The article intro image.<br />{acf.articles.index}: The article index.<br />{acf.articles.total}: The number of total articles to show.<br /><br />For a complete list of Smart Tags, please read the documentation page."
ACF_ARTICLES_ORDER="Order"
ACF_ARTICLES_ORDER_DESC="Select how to order the items."
ACF_ARTICLES_ID_ASC="ID (Asc)"
ACF_ARTICLES_ID_DESC="ID (Desc)"
ACF_ARTICLES_ORDERING_ASC="Ordering (Asc)"
ACF_ARTICLES_ORDERING_DESC="Ordering (Desc)"
ACF_ARTICLES_TITLE_ASC="Title (Asc)"
ACF_ARTICLES_TITLE_DESC="Title (Desc)"
ACF_ARTICLES_ALIAS_ASC="Alias (Asc)"
ACF_ARTICLES_ALIAS_DESC="Alias (Desc)"
ACF_ARTICLES_HITS_ASC="Hits (Asc)"
ACF_ARTICLES_HITS_DESC="Hits (Desc)"
ACF_ARTICLES_CREATED_ASC="Created Date (Asc)"
ACF_ARTICLES_CREATED_DESC="Created Date (Desc)"
ACF_ARTICLES_MODIFIED_ASC="Modified Date (Asc)"
ACF_ARTICLES_MODIFIED_DESC="Modified Date (Desc)"
ACF_ARTICLES_PUBLISH_UP_ASC="Published Date (Asc)"
ACF_ARTICLES_PUBLISH_UP_DESC="Published Date (Desc)"
ACF_ARTICLES_FEATURED_ASC="Featured (Asc)"
ACF_ARTICLES_FEATURED_DESC="Featured (Desc)"
ACF_ARTICLES_CATEGORY_LFT_ASC="Category Order (Asc)"
ACF_ARTICLES_CATEGORY_LFT_DESC="Category Order (Desc)"
ACF_ARTICLES_CATEGORY_TITLE_ASC="Category Title (Asc)"
ACF_ARTICLES_CATEGORY_TITLE_DESC="Category Title (Desc)"
ACF_ARTICLES_SELECT_ARTICLES="Select articles"
ACF_ARTICLES_SELECT_ARTICLE="Select an article"
ACF_ARTICLES_COLUMNS="Columns"
ACF_ARTICLES_COLUMNS_DESC="Select the columns of the layout."
ACF_ARTICLES_GAP="Gap"
ACF_ARTICLES_GAP_DESC="Select the gap between the items."
ACF_ARTICLES_INPUT_FILTERS="Input Filters"
ACF_ARTICLES_INPUT_FILTERS_DESC="These filters are applied to the articles that are displayed on the back-end."
ACF_ARTICLES_INPUT_OPTIONS="Input Options"
ACF_ARTICLES_MIN_ITEMS_REQUIRED="%s: You must select a minimum of %s articles."
ACF_ARTICLES_MAX_ITEMS_REQUIRED="%s: You must select a maximum of %s articles."
ACF_ARTICLES_FILTER_BY_STATUS="By Status"
ACF_ARTICLES_FILTER_STATUS_DESC="Set whether to filter the articles by their status."
ACF_ARTICLES_FILTER_STATUS_SELECTION_DESC="Select statuses to filter the articles."
ACF_ARTICLES_TYPE="Connection Options"
ACF_ARTICLES_TYPE_DESC="Select how the articles will be displayed.<br><br><strong>Manual Selection</strong>: Choose specific articles manually.<br><br><strong>Automatically</strong>: Automatically identify related articles by checking if the current article is linked to other ACF Articles fields that use the Manual Selection option.<br><strong>Note</strong>: By default, you must enable this custom field on each article. To automatically make all articles display the linked articles, set Default Value to 1/true."
ACF_ARTICLES_ARTICLES_FIELD="ACF - Articles fields"
ACF_ARTICLES_ARTICLES_FIELD_DESC="In order to automatically find articles, you must select at least one ACF - Articles field, and the current article must be linked to the selected ACF - Articles fields."
ACF_ARTICLES_ARTICLES_LINKED="Linked Articles"
ACF_ARTICLES_ARTICLES_LINKED_DESC="Make ACF - Articles automatically retrive articles that link to this field."
ACF_ARTICLES_MANUAL="Manual Selection"
ACF_ARTICLES_AUTO="Automatic Discovery"
ACF_ARTICLES_SELECT_ACF_ARTICLES="Select ACF - Articles fields"
ACF_ARTICLES_OUTPUT_FILTERS="Output Filters"
ACF_ARTICLES_OUTPUT_FILTERS_DESC="These filters are applied to the articles that are displayed on the front-end."
ACF_ARTICLES_LIMIT_ARTICLES="Limit Articles"
ACF_ARTICLES_LIMIT_ARTICLES_DESC="Define how many linked articles to display. Enter 0 for no limit."

View File

@ -0,0 +1,9 @@
; @package Advanced Custom Fields
; @version 2.8.8 Pro
;
; @author Tassos Marinos - http://www.tassos.gr/joomla-extensions
; @copyright Copyright (c) 2023 Tassos Marinos. All rights reserved.
; @license http://www.tassos.gr
ACF_ARTICLES="Fields - ACF Articles"
ACF_ARTICLES_DESC="Select and connect articles to each other."

View File

@ -0,0 +1,78 @@
; @package Advanced Custom Fields
; @version 2.8.8 Pro
;
; @author Tassos Marinos - http://www.tassos.gr/joomla-extensions
; @copyright Copyright (c) 2023 Tassos Marinos. All rights reserved.
; @license http://www.tassos.gr
PLG_FIELDS_ACFARTICLES_LABEL="ACF - Artículos"
ACF_ARTICLES="Campos - ACF Artículos"
ACF_ARTICLES_DESC="Seleccionar y conectar artículos entre sí."
ACF_ARTICLES_VALUE_DESC="Seleccione artículos para conectarse a este elemento."
ACF_ARTICLES_MIN_ARTICLES="Artículos Mínimos"
ACF_ARTICLES_MIN_ARTICLES_DESC="Establece un límite en los artículos mínimos que se pueden seleccionar."
ACF_ARTICLES_MAX_ARTICLES="Artículos Máximos"
ACF_ARTICLES_MAX_ARTICLES_DESC="Establece un límite en los artículos máximos que se pueden seleccionar."
ACF_ARTICLES_FILTER_BY_CATEGORY="Por Categoría"
ACF_ARTICLES_FILTER_CATEGORY_DESC="Establezca si desea filtrar los artículos por categorías."
ACF_ARTICLES_FILTER_CATEGORY_SELECTION_DESC="Seleccione categorías para filtrar los artículos."
ACF_ARTICLES_FILTER_BY_TAG="Por Etiqueta"
ACF_ARTICLES_FILTER_TAG_DESC="Establezca si desea filtrar los artículos por etiquetas."
ACF_ARTICLES_FILTER_TAG_SELECTION_DESC="Seleccione etiquetas para filtrar los artículos."
ACF_ARTICLES_FILTER_BY_AUTHOR="Por Autor"
ACF_ARTICLES_FILTER_AUTHOR_DESC="Establezca si desea filtrar los artículos por autor."
ACF_ARTICLES_FILTER_AUTHOR_SELECTION_DESC="Seleccione autores para filtrar los artículos."
ACF_ARTICLES_LAYOUT_DESC="Seleccione el diseño para mostrar los artículos."
ACF_ARTICLES_LAYOUT_CUSTOM="Diseño Personalizado"
ACF_ARTICLES_LAYOUT_CUSTOM_DESC="Ingrese el código HTML para cada elemento del artículo. También se admiten etiquetas inteligentes. <br><br>Para acceder a los datos de un artículo, utilice la etiqueta inteligente {acf.article.KEY} donde KEY es la clave del objeto del artículo. <br><br>Etiquetas inteligentes útiles: </br>{acf.article.link}: la URL del artículo <br>{acf.article .introtext}: el texto de introducción del artículo <br>{acf.article.images.image_intro}: la imagen de introducción del artículo. <br>{acf.articles.index}: el índice del artículo. <br>{acf.articles.total}: el número total de artículos que se mostrarán. <br><br>Para obtener una lista completa de etiquetas inteligentes, lea la página de documentación."
ACF_ARTICLES_ORDER="Orden"
ACF_ARTICLES_ORDER_DESC="Seleccione cómo ordenar los artículos."
ACF_ARTICLES_ID_ASC="ID (Asc)"
ACF_ARTICLES_ID_DESC="ID (Desc)"
ACF_ARTICLES_ORDERING_ASC="Ordenar (Asc)"
ACF_ARTICLES_ORDERING_DESC="Ordenar (Desc)"
ACF_ARTICLES_TITLE_ASC="Título (Asc)"
ACF_ARTICLES_TITLE_DESC="Título (Desc)"
ACF_ARTICLES_ALIAS_ASC="Alias (Asc)"
ACF_ARTICLES_ALIAS_DESC="Alias (Desc)"
ACF_ARTICLES_HITS_ASC="Golpes (Asc)"
ACF_ARTICLES_HITS_DESC="Golpes (Desc)"
ACF_ARTICLES_CREATED_ASC="Fecha de Creación (Asc)"
ACF_ARTICLES_CREATED_DESC="Fecha de Creación (Desc)"
ACF_ARTICLES_MODIFIED_ASC="Fecha de Modificación (Asc)"
ACF_ARTICLES_MODIFIED_DESC="Fecha de Modificación (Desc)"
ACF_ARTICLES_PUBLISH_UP_ASC="Fecha de Publicación (Asc)"
ACF_ARTICLES_PUBLISH_UP_DESC="Fecha de Publicación (Desc)"
ACF_ARTICLES_FEATURED_ASC="Características (Asc)"
ACF_ARTICLES_FEATURED_DESC="Características (Desc)"
ACF_ARTICLES_CATEGORY_LFT_ASC="Orden de Categoría (Asc)"
ACF_ARTICLES_CATEGORY_LFT_DESC="Orden de Categoría (Desc)"
ACF_ARTICLES_CATEGORY_TITLE_ASC="Título de Categoría (Asc)"
ACF_ARTICLES_CATEGORY_TITLE_DESC="Título de Categoría (Desc)"
ACF_ARTICLES_SELECT_ARTICLES="Seleccionar artículos"
ACF_ARTICLES_SELECT_ARTICLE="Seleccionar un artículo"
ACF_ARTICLES_COLUMNS="Columnas"
ACF_ARTICLES_COLUMNS_DESC="Seleccione las columnas del diseño."
ACF_ARTICLES_GAP="Espaciado"
ACF_ARTICLES_GAP_DESC="Seleccione el espacio entre los elementos."
ACF_ARTICLES_INPUT_FILTERS="Filtros de Entrada"
ACF_ARTICLES_INPUT_FILTERS_DESC="Estos filtros se aplican a los artículos que se muestran en el back-end."
ACF_ARTICLES_INPUT_OPTIONS="Opciones de Entrada"
ACF_ARTICLES_MIN_ITEMS_REQUIRED="%s: Debe seleccionar un mínimo de %s artículos."
ACF_ARTICLES_MAX_ITEMS_REQUIRED="%s: Debe seleccionar un máximo de %s artículos."
ACF_ARTICLES_FILTER_BY_STATUS="Por Estado"
ACF_ARTICLES_FILTER_STATUS_DESC="Establezca si desea filtrar los artículos por estados."
ACF_ARTICLES_FILTER_STATUS_SELECTION_DESC="Seleccione estados para filtrar los artículos."
ACF_ARTICLES_TYPE="Opciones de conexión"
ACF_ARTICLES_TYPE_DESC="Seleccione cómo se mostrarán los artículos.<br><br><strong>Selección manual</strong>: Elija artículos específicos manualmente.<br><br><strong>Automáticamente</strong>: Identifique automáticamente los artículos relacionados comprobando si el artículo actual está vinculado a otros campos de artículos ACF que utilizan la opción de selección manual.<br><strong>Nota</strong>: De forma predeterminada, debe habilitar este campo personalizado en cada artículo. Para hacer que todos los artículos muestren automáticamente los artículos vinculados, establezca el Valor predeterminado en 1/true."
ACF_ARTICLES_ARTICLES_FIELD="ACF - Campos de artículos"
ACF_ARTICLES_ARTICLES_FIELD_DESC="Para encontrar automáticamente artículos, debes seleccionar al menos un ACF - Campo de Artículos, y el artículo actual debe estar vinculado a ACF - Campos de Artículos."
ACF_ARTICLES_ARTICLES_LINKED="Artículos vinculados"
ACF_ARTICLES_ARTICLES_LINKED_DESC="Hacer que AC - Artículos recupere automáticamente los artículos que estan vinculados con este campo."
ACF_ARTICLES_MANUAL="Selección Manual"
ACF_ARTICLES_AUTO="Descubrimiento automático"
ACF_ARTICLES_SELECT_ACF_ARTICLES="Seleccionar ACF - Campos de artículos"
ACF_ARTICLES_OUTPUT_FILTERS="Filtros de salida"
ACF_ARTICLES_OUTPUT_FILTERS_DESC="Estos filtros se aplican a los artículos que se muestran en el front-end."
ACF_ARTICLES_LIMIT_ARTICLES="Limitar Artículos"
ACF_ARTICLES_LIMIT_ARTICLES_DESC="Define cuántos artículos vinculados mostrar. Introduce 0 para no tener límite."

View File

@ -0,0 +1,9 @@
; @package Advanced Custom Fields
; @version 2.8.8 Pro
;
; @author Tassos Marinos - http://www.tassos.gr/joomla-extensions
; @copyright Copyright (c) 2023 Tassos Marinos. All rights reserved.
; @license http://www.tassos.gr
ACF_ARTICLES="Campos - ACF Articulos"
ACF_ARTICLES_DESC="Seleccionar y conectar artículos entre sí."

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams" addfieldpath="plugins/fields/acfarticles/fields">
<fieldset name="fieldparams">
<field name="articles_type" type="list"
label="ACF_ARTICLES_TYPE"
description="ACF_ARTICLES_TYPE_DESC"
default="default">
<option value="default">ACF_ARTICLES_MANUAL</option>
<option value="linked">ACF_ARTICLES_AUTO</option>
</field>
<field type="spacer" name="auto_discovery_label"
label="ACF_ARTICLES_AUTO"
class="acf"
showon="articles_type:linked"
/>
<field name="articles_fields" type="ACFArticlesFields"
label="ACF_ARTICLES_ARTICLES_FIELD"
description="ACF_ARTICLES_ARTICLES_FIELD_DESC"
multiple="true"
showon="articles_type:linked"
/>
<field type="number" name="limit"
label="ACF_ARTICLES_LIMIT_ARTICLES"
description="ACF_ARTICLES_LIMIT_ARTICLES_DESC"
min="0"
default="0"
showon="articles_type:linked"
/>
<field name="order" type="list"
label="ACF_ARTICLES_ORDER"
description="ACF_ARTICLES_ORDER_DESC"
multiple="true"
layout="joomla.form.field.list-fancy-select"
default="id_desc">
<option value="id_asc">ACF_ARTICLES_ID_ASC</option>
<option value="id_desc">ACF_ARTICLES_ID_DESC</option>
<option value="ordering_asc">ACF_ARTICLES_ORDERING_ASC</option>
<option value="ordering_desc">ACF_ARTICLES_ORDERING_DESC</option>
<option value="title_asc">ACF_ARTICLES_TITLE_ASC</option>
<option value="title_desc">ACF_ARTICLES_TITLE_DESC</option>
<option value="alias_asc">ACF_ARTICLES_ALIAS_ASC</option>
<option value="alias_desc">ACF_ARTICLES_ALIAS_DESC</option>
<option value="hits_asc">ACF_ARTICLES_HITS_ASC</option>
<option value="hits_desc">ACF_ARTICLES_HITS_DESC</option>
<option value="created_asc">ACF_ARTICLES_CREATED_ASC</option>
<option value="created_desc">ACF_ARTICLES_CREATED_DESC</option>
<option value="modified_asc">ACF_ARTICLES_MODIFIED_ASC</option>
<option value="modified_desc">ACF_ARTICLES_MODIFIED_DESC</option>
<option value="publish_up_asc">ACF_ARTICLES_PUBLISH_UP_ASC</option>
<option value="publish_up_desc">ACF_ARTICLES_PUBLISH_UP_DESC</option>
<option value="featured_asc">ACF_ARTICLES_FEATURED_ASC</option>
<option value="featured_desc">ACF_ARTICLES_FEATURED_DESC</option>
<option value="category_lft_asc">ACF_ARTICLES_CATEGORY_LFT_ASC</option>
<option value="category_lft_desc">ACF_ARTICLES_CATEGORY_LFT_DESC</option>
<option value="category_title_asc">ACF_ARTICLES_CATEGORY_TITLE_ASC</option>
<option value="category_title_desc">ACF_ARTICLES_CATEGORY_TITLE_DESC</option>
</field>
<field type="spacer" name="input_options_label"
label="ACF_ARTICLES_INPUT_OPTIONS"
class="acf"
showon="articles_type:default"
/>
<field name="min_articles" type="number"
label="ACF_ARTICLES_MIN_ARTICLES"
description="ACF_ARTICLES_MIN_ARTICLES_DESC"
min="0"
default="0"
showon="articles_type:default"
/>
<field name="max_articles" type="number"
label="ACF_ARTICLES_MAX_ARTICLES"
description="ACF_ARTICLES_MAX_ARTICLES_DESC"
min="0"
default="0"
showon="articles_type:default"
/>
<field type="spacer" name="filters_label"
label="ACF_ARTICLES_INPUT_FILTERS"
description="ACF_ARTICLES_INPUT_FILTERS_DESC"
class="acf"
showon="articles_type:default"
/>
<field type="spacer" name="linked_filters_label"
label="ACF_ARTICLES_OUTPUT_FILTERS"
description="ACF_ARTICLES_OUTPUT_FILTERS_DESC"
class="acf"
showon="articles_type:linked"
/>
<field name="filters_category_enabled" type="nrtoggle"
label="ACF_ARTICLES_FILTER_BY_CATEGORY"
description="ACF_ARTICLES_FILTER_CATEGORY_DESC"
/>
<field name="filters_category_value" type="nr_content"
label="NR_CATEGORIES"
description="ACF_ARTICLES_FILTER_CATEGORY_SELECTION_DESC"
group="categories"
multiple="true"
showon="fieldparams.filters_category_enabled:1"
/>
<field name="filters_category_inc_children" type="radio"
default="0"
label="NR_ALSO_ON_CHILD_ITEMS"
description="NR_ALSO_ON_CHILD_ITEMS_DESC"
class="btn-group btn-group-yesno"
showon="fieldparams.filters_category_enabled:1">
<option value="0">JNO</option>
<option value="1">JYES</option>
<option value="2">NR_ONLY</option>
</field>
<field name="filters_tag_enabled" type="nrtoggle"
label="ACF_ARTICLES_FILTER_BY_TAG"
description="ACF_ARTICLES_FILTER_TAG_DESC"
/>
<field name="filters_tag_value" type="componentitems"
label="NR_TAG"
description="ACF_ARTICLES_FILTER_TAG_SELECTION_DESC"
multiple="true"
table="tags"
column_title="title"
column_state="published"
where="published = 1 AND level > 0"
showon="fieldparams.filters_tag_enabled:1"
/>
<field name="filters_author_enabled" type="nrtoggle"
label="ACF_ARTICLES_FILTER_BY_AUTHOR"
description="ACF_ARTICLES_FILTER_AUTHOR_DESC"
/>
<field name="filters_author_value" type="componentitems"
label="NR_AUTHOR"
description="ACF_ARTICLES_FILTER_AUTHOR_SELECTION_DESC"
multiple="true"
table="users"
join="#__content as c ON c.created_by = i.id"
column_title="i.name"
column_state="i.block"
group="i.id"
showon="fieldparams.filters_author_enabled:1"
/>
<field name="filters_status_value" type="list"
label="ACF_ARTICLES_FILTER_BY_STATUS"
description="ACF_ARTICLES_FILTER_STATUS_SELECTION_DESC"
multiple="true"
layout="joomla.form.field.list-fancy-select"
default="1">
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field type="spacer" name="layout_label"
label="NR_LAYOUT"
class="acf"
/>
<field name="layout" type="NRImagesSelector"
columns="4"
width="600px"
images="/media/plg_fields_acfarticles/img"
label="NR_LAYOUT"
description="ACF_ARTICLES_LAYOUT_DESC"
default="media/plg_fields_acfarticles/img/alist.svg"
/>
<field name="devices_columns" type="NRResponsiveControl"
showon="layout:media/plg_fields_acfarticles/img/astylea.svg[OR]layout:media/plg_fields_acfarticles/img/astyleb.svg"
label="ACF_ARTICLES_COLUMNS"
description="ACF_ARTICLES_COLUMNS_DESC">
<subform>
<field name="columns" type="number"
class="input-small"
default="2"
hint="3"
min="1"
max="6" />
</subform>
</field>
<field name="devices_gap" type="NRResponsiveControl"
showon="layout:media/plg_fields_acfarticles/img/astylea.svg[OR]layout:media/plg_fields_acfarticles/img/astyleb.svg"
label="ACF_ARTICLES_GAP"
description="ACF_ARTICLES_GAP_DESC">
<subform>
<field name="gap" type="nrnumber"
class="input-small"
default="10"
hint="10"
addon="px" />
</subform>
</field>
<field name="custom_layout" type="editor"
label="ACF_ARTICLES_LAYOUT_CUSTOM"
description="ACF_ARTICLES_LAYOUT_CUSTOM_DESC"
showon="layout:media/plg_fields_acfarticles/img/custom.svg"
editor="codemirror"
filter="raw"
/>
</fieldset>
</fields>
</form>

View File

@ -0,0 +1,691 @@
<?php
/**
* Installer Script Helper
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2016 Tassos Marinos All Rights Reserved
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
*/
defined('_JEXEC') or die;
use Joomla\CMS\Installer\Installer;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
class PlgFieldsAcfarticlesInstallerScriptHelper
{
public $name = '';
public $alias = '';
public $extname = '';
public $extension_type = '';
public $plugin_folder = 'system';
public $module_position = 'status';
public $client_id = 1;
public $install_type = 'install';
public $show_message = true;
public $autopublish = true;
public $db = null;
public $app = null;
public $installedVersion;
public function __construct(&$params)
{
$this->extname = $this->extname ?: $this->alias;
$this->db = Factory::getDbo();
$this->app = Factory::getApplication();
$this->installedVersion = $this->getVersion($this->getInstalledXMLFile());
}
/**
* Preflight event
*
* @param string
* @param JAdapterInstance
*
* @return boolean
*/
public function preflight($route, $adapter)
{
if (!in_array($route, array('install', 'update')))
{
return;
}
Factory::getLanguage()->load('plg_system_novaraininstaller', JPATH_PLUGINS . '/system/novaraininstaller');
if ($this->show_message && $this->isInstalled())
{
$this->install_type = 'update';
}
if ($this->onBeforeInstall() === false)
{
return false;
}
}
/**
* Preflight event
*
* @param string
* @param JAdapterInstance
*
* @return boolean
*/
public function postflight($route, $adapter)
{
Factory::getLanguage()->load($this->getPrefix() . '_' . $this->extname, $this->getMainFolder());
if (!in_array($route, array('install', 'update')))
{
return;
}
if ($this->onAfterInstall() === false)
{
return false;
}
if ($route == 'install' && $this->autopublish)
{
$this->publishExtension();
}
if ($this->show_message)
{
$this->addInstalledMessage();
}
Factory::getCache()->clean('com_plugins');
Factory::getCache()->clean('_system');
}
public function isInstalled()
{
if (!is_file($this->getInstalledXMLFile()))
{
return false;
}
$query = $this->db->getQuery(true)
->select('extension_id')
->from('#__extensions')
->where($this->db->quoteName('type') . ' = ' . $this->db->quote($this->extension_type))
->where($this->db->quoteName('element') . ' = ' . $this->db->quote($this->getElementName()));
$this->db->setQuery($query, 0, 1);
$result = $this->db->loadResult();
return empty($result) ? false : true;
}
public function getMainFolder()
{
switch ($this->extension_type)
{
case 'plugin' :
return JPATH_SITE . '/plugins/' . $this->plugin_folder . '/' . $this->extname;
case 'component' :
return JPATH_ADMINISTRATOR . '/components/com_' . $this->extname;
case 'module' :
return JPATH_ADMINISTRATOR . '/modules/mod_' . $this->extname;
case 'library' :
return JPATH_SITE . '/libraries/' . $this->extname;
}
}
public function getInstalledXMLFile()
{
return $this->getXMLFile($this->getMainFolder());
}
public function getCurrentXMLFile()
{
return $this->getXMLFile(__DIR__);
}
public function getXMLFile($folder)
{
switch ($this->extension_type)
{
case 'module' :
return $folder . '/mod_' . $this->extname . '.xml';
default :
return $folder . '/' . $this->extname . '.xml';
}
}
public function foldersExist($folders = array())
{
foreach ($folders as $folder)
{
if (is_dir($folder))
{
return true;
}
}
return false;
}
public function publishExtension()
{
switch ($this->extension_type)
{
case 'plugin' :
$this->publishPlugin();
case 'module' :
$this->publishModule();
}
}
public function publishPlugin()
{
$query = $this->db->getQuery(true)
->update('#__extensions')
->set($this->db->quoteName('enabled') . ' = 1')
->where($this->db->quoteName('type') . ' = ' . $this->db->quote('plugin'))
->where($this->db->quoteName('element') . ' = ' . $this->db->quote($this->extname))
->where($this->db->quoteName('folder') . ' = ' . $this->db->quote($this->plugin_folder));
$this->db->setQuery($query);
$this->db->execute();
}
public function publishModule()
{
// Get module id
$query = $this->db->getQuery(true)
->select('id')
->from('#__modules')
->where($this->db->quoteName('module') . ' = ' . $this->db->quote('mod_' . $this->extname))
->where($this->db->quoteName('client_id') . ' = ' . (int) $this->client_id);
$this->db->setQuery($query, 0, 1);
$id = $this->db->loadResult();
if (!$id)
{
return;
}
// check if module is already in the modules_menu table (meaning is is already saved)
$query->clear()
->select('moduleid')
->from('#__modules_menu')
->where($this->db->quoteName('moduleid') . ' = ' . (int) $id);
$this->db->setQuery($query, 0, 1);
$exists = $this->db->loadResult();
if ($exists)
{
return;
}
// Get highest ordering number in position
$query->clear()
->select('ordering')
->from('#__modules')
->where($this->db->quoteName('position') . ' = ' . $this->db->quote($this->module_position))
->where($this->db->quoteName('client_id') . ' = ' . (int) $this->client_id)
->order('ordering DESC');
$this->db->setQuery($query, 0, 1);
$ordering = $this->db->loadResult();
$ordering++;
// publish module and set ordering number
$query->clear()
->update('#__modules')
->set($this->db->quoteName('published') . ' = 1')
->set($this->db->quoteName('ordering') . ' = ' . (int) $ordering)
->set($this->db->quoteName('position') . ' = ' . $this->db->quote($this->module_position))
->where($this->db->quoteName('id') . ' = ' . (int) $id);
$this->db->setQuery($query);
$this->db->execute();
// add module to the modules_menu table
$query->clear()
->insert('#__modules_menu')
->columns(array($this->db->quoteName('moduleid'), $this->db->quoteName('menuid')))
->values((int) $id . ', 0');
$this->db->setQuery($query);
$this->db->execute();
}
public function addInstalledMessage()
{
Factory::getApplication()->enqueueMessage(
Text::sprintf(
Text::_($this->install_type == 'update' ? 'NRI_THE_EXTENSION_HAS_BEEN_UPDATED_SUCCESSFULLY' : 'NRI_THE_EXTENSION_HAS_BEEN_INSTALLED_SUCCESSFULLY'),
'<strong>' . Text::_($this->name) . '</strong>',
'<strong>' . $this->getVersion() . '</strong>',
$this->getFullType()
)
);
}
public function getPrefix()
{
switch ($this->extension_type)
{
case 'plugin';
return Text::_('plg_' . strtolower($this->plugin_folder));
case 'component':
return Text::_('com');
case 'module':
return Text::_('mod');
case 'library':
return Text::_('lib');
default:
return $this->extension_type;
}
}
public function getElementName($type = null, $extname = null)
{
$type = is_null($type) ? $this->extension_type : $type;
$extname = is_null($extname) ? $this->extname : $extname;
switch ($type)
{
case 'component' :
return 'com_' . $extname;
case 'module' :
return 'mod_' . $extname;
case 'plugin' :
default:
return $extname;
}
}
public function getFullType()
{
return Text::_('NRI_' . strtoupper($this->getPrefix()));
}
public function isPro()
{
$versionFile = __DIR__ . "/version.php";
// If version file does not exist we assume a PRO version
if (!is_file($versionFile))
{
return true;
}
// Load version file
require_once $versionFile;
return (bool) $NR_PRO;
}
public function getVersion($file = '')
{
$file = $file ?: $this->getCurrentXMLFile();
if (!is_file($file))
{
return '';
}
$xml = Installer::parseXMLInstallFile($file);
if (!$xml || !isset($xml['version']))
{
return '';
}
return $xml['version'];
}
/**
* Checks wether the extension can be installed or not
*
* @return boolean
*/
public function canInstall()
{
// The extension is not installed yet. Accept Install.
if (!$installed_version = $this->getVersion($this->getInstalledXMLFile()))
{
return true;
}
// Path to extension's version file
$versionFile = $this->getMainFolder() . "/version.php";
$NR_PRO = true;
// If version file does not exist we assume we have a PRO version installed
if (file_exists($versionFile))
{
require_once($versionFile);
}
// The free version is installed. Accept install.
if (!(bool)$NR_PRO)
{
return true;
}
// Current package is a PRO version. Accept install.
if ($this->isPro())
{
return true;
}
// User is trying to update from PRO version to FREE. Do not accept install.
Factory::getLanguage()->load($this->getPrefix() . '_' . $this->extname, __DIR__);
Factory::getApplication()->enqueueMessage(
Text::_('NRI_ERROR_PRO_TO_FREE'), 'error'
);
Factory::getApplication()->enqueueMessage(
html_entity_decode(
Text::sprintf(
'NRI_ERROR_UNINSTALL_FIRST',
'<a href="http://www.tassos.gr/joomla-extensions/' . $this->getUrlAlias() . '" target="_blank">',
'</a>',
Text::_($this->name)
)
), 'error'
);
return false;
}
/**
* Returns the URL alias of the extension.
*
* @return string
*/
private function getUrlAlias()
{
$alias = $this->alias;
switch ($alias)
{
case 'smilepack':
$alias = 'smile-pack';
break;
case 'convertforms':
$alias = 'convert-forms';
break;
case 'rstbox':
$alias = 'engagebox';
break;
case 'gsd':
$alias = 'google-structured-data';
break;
}
// ACF
if ($this->plugin_folder === 'fields' && ($alias === 'acf' || $this->startsWith($alias, 'acf')))
{
$alias = 'advanced-custom-fields';
}
return $alias;
}
/**
* Checks whether string starts with substring.
*
* @param string $string
* @param string $query
*
* @return bool
*/
public static function startsWith($string, $query)
{
return substr($string, 0, strlen($query)) === $query;
}
/**
* Checks if current version is newer than the installed one
* Used for Novarain Framework
*
* @return boolean [description]
*/
public function isNewer()
{
if (!$installed_version = $this->getVersion($this->getInstalledXMLFile()))
{
return true;
}
$package_version = $this->getVersion();
return version_compare($installed_version, $package_version, '<=');
}
/**
* Helper method triggered before installation
*
* @return bool
*/
public function onBeforeInstall()
{
if (!$this->canInstall())
{
return false;
}
}
/**
* Helper method triggered after installation
*/
public function onAfterInstall()
{
}
/**
* Delete files
*
* @param array $folders
*/
public function deleteFiles($files = array())
{
foreach ($files as $key => $file)
{
if (!is_file($file))
{
continue;
}
File::delete($file);
}
}
/**
* Deletes folders
*
* @param array $folders
*/
public function deleteFolders($folders = array())
{
foreach ($folders as $folder)
{
if (!is_dir($folder))
{
continue;
}
Folder::delete($folder);
}
}
public function dropIndex($table, $index)
{
$db = $this->db;
// Check if index exists first
$query = 'SHOW INDEX FROM ' . $db->quoteName('#__' . $table) . ' WHERE KEY_NAME = ' . $db->quote($index);
$db->setQuery($query);
$db->execute();
if (!$db->loadResult())
{
return;
}
// Remove index
$query = 'ALTER TABLE ' . $db->quoteName('#__' . $table) . ' DROP INDEX ' . $db->quoteName($index);
$db->setQuery($query);
$db->execute();
}
public function dropUnwantedTables($tables) {
if (!$tables) {
return;
}
foreach ($tables as $table) {
$query = "DROP TABLE IF EXISTS #__".$this->db->escape($table);
$this->db->setQuery($query);
$this->db->execute();
}
}
public function dropUnwantedColumns($table, $columns) {
if (!$columns || !$table) {
return;
}
$db = $this->db;
// Check if columns exists in database
function qt($n) {
return(Factory::getDBO()->quote($n));
}
$query = 'SHOW COLUMNS FROM #__'.$table.' WHERE Field IN ('.implode(",", array_map("qt", $columns)).')';
$db->setQuery($query);
$rows = $db->loadColumn(0);
// Abort if we don't have any rows
if (!$rows) {
return;
}
// Let's remove the columns
$q = "";
foreach ($rows as $key => $column) {
$comma = (($key+1) < count($rows)) ? "," : "";
$q .= "drop ".$this->db->escape($column).$comma;
}
$query = "alter table #__".$table." $q";
$db->setQuery($query);
$db->execute();
}
public function fetch($table, $columns = "*", $where = null, $singlerow = false) {
if (!$table) {
return;
}
$db = $this->db;
$query = $db->getQuery(true);
$query
->select($columns)
->from("#__$table");
if (isset($where)) {
$query->where("$where");
}
$db->setQuery($query);
return ($singlerow) ? $db->loadObject() : $db->loadObjectList();
}
/**
* Load the Novarain Framework
*
* @return boolean
*/
public function loadFramework()
{
if (is_file(JPATH_PLUGINS . '/system/nrframework/autoload.php'))
{
include_once JPATH_PLUGINS . '/system/nrframework/autoload.php';
}
}
/**
* Re-orders plugin after passed array of plugins
*
* @param string $plugin Plugin element name
* @param array $lowerPluginOrder Array of plugin element names
*
* @return boolean
*/
public function pluginOrderAfter($lowerPluginOrder)
{
if (!is_array($lowerPluginOrder) || !count($lowerPluginOrder))
{
return;
}
$db = $this->db;
// Get plugins max order
$query = $db->getQuery(true);
$query
->select($db->quoteName('b.ordering'))
->from($db->quoteName('#__extensions', 'b'))
->where($db->quoteName('b.element') . ' IN ("'.implode("\",\"",$lowerPluginOrder).'")')
->order('b.ordering desc');
$db->setQuery($query);
$maxOrder = $db->loadResult();
if (is_null($maxOrder))
{
return;
}
// Get plugin details
$query
->clear()
->select(array($db->quoteName('extension_id'), $db->quoteName('ordering')))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('element') . ' = ' . $db->quote($this->alias));
$db->setQuery($query);
$pluginInfo = $db->loadObject();
if (!isset($pluginInfo->ordering) || $pluginInfo->ordering > $maxOrder)
{
return;
}
// Update the new plugin order
$object = new stdClass();
$object->extension_id = $pluginInfo->extension_id;
$object->ordering = ($maxOrder + 1);
try {
$db->updateObject('#__extensions', $object, 'extension_id');
} catch (Exception $e) {
return $e->getMessage();
}
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted access');
require_once __DIR__ . '/script.install.helper.php';
class PlgFieldsACFArticlesInstallerScript extends PlgFieldsACFArticlesInstallerScriptHelper
{
public $alias = 'acfarticles';
public $extension_type = 'plugin';
public $plugin_folder = "fields";
public $show_message = false;
}

View File

@ -0,0 +1,86 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
if (!$articles = $field->value)
{
return;
}
$routerHelper = defined('nrJ4') ? 'Joomla\Component\Content\Site\Helper\RouteHelper' : 'ContentHelperRoute';
// Get the layout
$layout = $fieldParams->get('layout', 'media/plg_fields_acfarticles/img/alist.svg');
$layout = str_replace(['media/plg_fields_acfarticles/img/', '.svg'], '', $layout);
$layout = ltrim($layout, 'a');
$customLayout = $fieldParams->get('custom_layout', '');
if ($layout === 'custom' && !$customLayout)
{
return;
}
$id = 'acf_articles_' . $item->id . '_' . $field->id;
// Set the wrapper classes
$classes = [];
$classes[] = $id;
$classes[] = 'layout-' . $layout;
if (in_array($layout, ['stylea', 'styleb']))
{
$classes[] = 'layout-grid';
}
// Set columns and gap
if (in_array($layout, ['stylea', 'styleb']))
{
// Get columns and gap
$columns = $fieldParams->get('devices_columns.columns', []);
$gap = $fieldParams->get('devices_gap.gap', []);
Factory::getDocument()->addStyleDeclaration('
.acfarticles-field-wrapper.' . $id . ' {
--columns: ' . $columns['desktop'] . ';
--gap: ' . $gap['desktop'] . 'px;
}
@media only screen and (max-width: 991px) {
.acfarticles-field-wrapper.' . $id . ' {
--columns: ' . $columns['tablet'] . ';
--gap: ' . $gap['tablet'] . 'px;
}
}
@media only screen and (max-width: 575px) {
.acfarticles-field-wrapper.' . $id . ' {
--columns: ' . $columns['mobile'] . ';
--gap: ' . $gap['mobile'] . 'px;
}
}
');
}
$html = '<div class="acfarticles-field-wrapper ' . implode(' ', $classes) . '">';
$path = __DIR__ . '/layouts/' . $layout . '.php';
if (file_exists($path))
{
require $path;
}
$html .= '</div>';
echo $html;

View File

@ -0,0 +1,39 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
$customLayout = HTMLHelper::_('content.prepare', $customLayout);
$st = new \NRFramework\SmartTags();
// Add total articles
$st->add(['total' => count($articles)], 'acf.articles.');
// Set the pattern
$pattern = '/\{(acf\.)?article\.([^}]+)\}/';
foreach ($articles as $index => $article)
{
// Add article index
$st->add(['index' => $index + 1], 'acf.articles.');
// Set the replacement
$replacement = '{article.$2 --id=' . $article['id'] . ' --prepareCustomFields=false}';
// Get updated layout
$tmpCustomLayout = preg_replace($pattern, $replacement, $customLayout);
$html .= $st->replace($tmpCustomLayout);
}

View File

@ -0,0 +1,24 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
$html .= '<ul>';
foreach ($articles as $article)
{
$html .= '<li><a href="' . Route::_($routerHelper::getArticleRoute($article['id'], $article['catid'], $article['language'])) . '">' . $article['title'] . '</a></li>';
}
$html .= '</ul>';

View File

@ -0,0 +1,47 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Router\Route;
use Joomla\CMS\HTML\HTMLHelper;
if (defined('nrJ4'))
{
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->registerAndUseStyle('acf_articles_style', 'plg_fields_acfarticles/style.css');
}
else
{
HTMLHelper::stylesheet('plg_fields_acfarticles/style.css', ['relative' => true, 'version' => 'auto']);
}
foreach ($articles as $article)
{
$image = '';
if (isset($article['images']) && $image = json_decode($article['images']))
{
$image = $image->image_intro ?: $image->image_fulltext;
}
$html .= '<div class="acfarticle-item">';
if ($image)
{
$html .= '<img src="' . $image . '" class="acfarticle-item--image" alt="' . $article['title'] . '" loading="lazy" />';
}
$html .= '<a href="' . Route::_($routerHelper::getArticleRoute($article['id'], $article['catid'], $article['language'])) . '" class="acfarticle-item--content--title">' . $article['title'] . '</a>';
$html .= '</div>';
}

View File

@ -0,0 +1,56 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Router\Route;
use Joomla\CMS\HTML\HTMLHelper;
if (defined('nrJ4'))
{
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->registerAndUseStyle('acf_articles_style', 'plg_fields_acfarticles/style.css');
}
else
{
HTMLHelper::stylesheet('plg_fields_acfarticles/style.css', ['relative' => true, 'version' => 'auto']);
}
foreach ($articles as $article)
{
$image = '';
if (isset($article['images']) && $image = json_decode($article['images']))
{
$image = $image->image_intro ?: $image->image_fulltext;
}
$html .= '<div class="acfarticle-item">';
if ($image)
{
$html .= '<img src="' . $image . '" class="acfarticle-item--image" alt="' . $article['title'] . '" loading="lazy" />';
}
$html .= '<div class="acfarticle-item--content">';
$html .= '<a href="' . Route::_($routerHelper::getArticleRoute($article['id'], $article['catid'], $article['language'])) . '" class="acfarticle-item--content--title">' . $article['title'] . '</a>';
// Get the article excerpt
if ($excerpt = substr(strip_tags($article['introtext']), 0, 200))
{
// Add the excerpt
$html .= '<div class="acfarticle-item--content--excerpt">' . $excerpt . '...</div>';
}
$html .= '</div></div>';
}

View File

@ -0,0 +1,16 @@
<?php
/**
* @package Advanced Custom Fields
* @version 2.8.8 Pro
*
* @author Tassos Marinos <info@tassos.gr>
* @link http://www.tassos.gr
* @copyright Copyright © 2023 Tassos Marinos All Rights Reserved
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/
defined('_JEXEC') or die('Restricted Access');
$NR_PRO = "1";
?>