Featured

Manche Items sind etwas Besonderes und für sie gibt es in Joomla! ein spezielles Attribut: featured. Dieser Teil der Artikelserie fügt featured zu unserer Komponente hinzu.

Für Ungeduldige

Sieh dir den geänderten Programmcode in der Diff-Ansicht an und übernimm diese Änderungen in deine Entwicklungsversion.

// https://github.com/astridx/boilerplate/compare/t23...t24.diff

diff --git a/src/administrator/components/com_foos/forms/foo.xml b/src/administrator/components/com_foos/forms/foo.xml
index 1b8a4c73..37a9c36b 100644
-- a/src/administrator/components/com_foos/forms/foo.xml
++ b/src/administrator/components/com_foos/forms/foo.xml
@@ -39,6 +39,17 @@
 			<option value="*">JALL</option>
 		</field>

		<field
			name="featured"
			type="radio"
			class="switcher"
			label="JFEATURED"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

 		<field
 			name="published"
 			type="list"
diff --git a/src/administrator/components/com_foos/sql/install.mysql.utf8.sql b/src/administrator/components/com_foos/sql/install.mysql.utf8.sql
index 862fa7c9..291b695a 100644
-- a/src/administrator/components/com_foos/sql/install.mysql.utf8.sql
++ b/src/administrator/components/com_foos/sql/install.mysql.utf8.sql
@@ -42,3 +42,6 @@ ALTER TABLE `#__foos_details` ADD COLUMN `checked_out_time` datetime AFTER `alia

 ALTER TABLE `#__foos_details` ADD KEY `idx_checkout` (`checked_out`);

ALTER TABLE `#__foos_details` ADD COLUMN  `featured` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT 'Set if foo is featured.';

ALTER TABLE `#__foos_details` ADD KEY `idx_featured_catid` (`featured`,`catid`);
diff --git a/src/administrator/components/com_foos/sql/updates/mysql/24.0.0.sql b/src/administrator/components/com_foos/sql/updates/mysql/24.0.0.sql
new file mode 100644
index 00000000..24c42c39
-- /dev/null
++ b/src/administrator/components/com_foos/sql/updates/mysql/24.0.0.sql
@@ -0,0 +1,3 @@
ALTER TABLE `#__foos_details` ADD COLUMN  `featured` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT 'Set if foo is featured.';

ALTER TABLE `#__foos_details` ADD KEY `idx_featured_catid` (`featured`,`catid`);
diff --git a/src/administrator/components/com_foos/src/Controller/FoosController.php b/src/administrator/components/com_foos/src/Controller/FoosController.php
index 1aab8084..8711eadc 100644
-- a/src/administrator/components/com_foos/src/Controller/FoosController.php
++ b/src/administrator/components/com_foos/src/Controller/FoosController.php
@@ -11,6 +11,8 @@

 \defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\Utilities\ArrayHelper;
 use Joomla\CMS\Application\CMSApplication;
 use Joomla\CMS\MVC\Controller\AdminController;
 use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
@@ -38,6 +40,65 @@ class FoosController extends AdminController
 	public function __construct($config = array(), MVCFactoryInterface $factory = null, $app = null, $input = null)
 	{
 		parent::__construct($config, $factory, $app, $input);

		$this->registerTask('unfeatured', 'featured');
	}

	/**
	 * Method to toggle the featured setting of a list of foos.
	 *
	 * @return  void
	 *
	 * @since   __BUMP_VERSION__
	 */
	public function featured()
	{
		// Check for request forgeries
		$this->checkToken();

		$ids    = $this->input->get('cid', array(), 'array');
		$values = array('featured' => 1, 'unfeatured' => 0);
		$task   = $this->getTask();
		$value  = ArrayHelper::getValue($values, $task, 0, 'int');

		$model  = $this->getModel();

		// Access checks.
		foreach ($ids as $i => $id)
		{
			$item = $model->getItem($id);

			if (!$this->app->getIdentity()->authorise('core.edit.state', 'com_foos.category.' . (int) $item->catid))
			{
				// Prune items that you can't change.
				unset($ids[$i]);
				$this->app->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'notice');
			}
		}

		if (empty($ids))
		{
			$this->app->enqueueMessage(Text::_('COM_FOOS_NO_ITEM_SELECTED'), 'warning');
		}
		else
		{
			// Publish the items.
			if (!$model->featured($ids, $value))
			{
				$this->app->enqueueMessage($model->getError(), 'warning');
			}

			if ($value == 1)
			{
				$message = Text::plural('COM_FOOS_N_ITEMS_FEATURED', count($ids));
			}
			else
			{
				$message = Text::plural('COM_FOOS_N_ITEMS_UNFEATURED', count($ids));
			}
		}

		$this->setRedirect('index.php?option=com_foos&view=foos', $message);
 	}

 	/**
diff --git a/src/administrator/components/com_foos/src/Model/FooModel.php b/src/administrator/components/com_foos/src/Model/FooModel.php
index 80ff2907..8a27f382 100644
-- a/src/administrator/components/com_foos/src/Model/FooModel.php
++ b/src/administrator/components/com_foos/src/Model/FooModel.php
@@ -15,6 +15,8 @@
 use Joomla\CMS\Language\Associations;
 use Joomla\CMS\MVC\Model\AdminModel;
 use Joomla\CMS\Language\LanguageHelper;
use Joomla\Database\ParameterType;
use Joomla\Utilities\ArrayHelper;

 /**
  * Item Model for a Foo.
@@ -132,6 +134,59 @@ public function getItem($pk = null)
 		return $item;
 	}

	/**
	 * Method to toggle the featured setting of foos.
	 *
	 * @param   array    $pks    The ids of the items to toggle.
	 * @param   integer  $value  The value to toggle to.
	 *
	 * @return  boolean  True on success.
	 *
	 * @since   __BUMP_VERSION__
	 */
	public function featured($pks, $value = 0)
	{
		// Sanitize the ids.
		$pks = ArrayHelper::toInteger((array) $pks);

		if (empty($pks))
		{
			$this->setError(Text::_('COM_FOOS_NO_ITEM_SELECTED'));

			return false;
		}

		$table = $this->getTable();

		try
		{
			$db = $this->getDbo();

			$query = $db->getQuery(true);
			$query->update($db->quoteName('#__foos_details'));
			$query->set($db->quoteName('featured') . ' = :featured');
			$query->whereIn($db->quoteName('id'), $pks);
			$query->bind(':featured', $value, ParameterType::INTEGER);

			$db->setQuery($query);

			$db->execute();
		}
		catch (\Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		$table->reorder();

		// Clean component's cache
		$this->cleanCache();

		return true;
	}

 	/**
 	 * Preprocess the form.
 	 *
diff --git a/src/administrator/components/com_foos/src/Model/FoosModel.php b/src/administrator/components/com_foos/src/Model/FoosModel.php
index 1e8d6c88..c5f62f0c 100644
-- a/src/administrator/components/com_foos/src/Model/FoosModel.php
++ b/src/administrator/components/com_foos/src/Model/FoosModel.php
@@ -44,6 +44,7 @@ public function __construct($config = array())
 				'published', 'a.published',
 				'access', 'a.access', 'access_level',
 				'ordering', 'a.ordering',
				'featured', 'a.featured',
 				'language', 'a.language', 'language_title',
 				'publish_up', 'a.publish_up',
 				'publish_down', 'a.publish_down',
@@ -59,6 +60,7 @@ public function __construct($config = array())

 		parent::__construct($config);
 	}

 	/**
 	 * Build an SQL query to load the list data.
 	 *
@@ -85,6 +87,7 @@ protected function getListQuery()
 						', a.checked_out_time' .
 						', a.language' .
 						', a.ordering' .
						', a.featured' .
 						', a.state' .
 						', a.published' .
 						', a.publish_up, a.publish_down'
@@ -195,6 +198,14 @@ protected function getListQuery()
 			}
 		}

		// Filter by featured.
		$featured = (string) $this->getState('filter.featured');

		if (in_array($featured, ['0','1']))
		{
			$query->where($db->quoteName('a.featured') . ' = ' . (int) $featured);
		}

 		// Add the list ordering clause.
 		$orderCol = $this->state->get('list.ordering', 'a.name');
 		$orderDirn = $this->state->get('list.direction', 'asc');
diff --git a/src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php b/src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php
index b3ca4cb1..cb8a39a4 100644
-- a/src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php
++ b/src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php
@@ -16,6 +16,7 @@
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\Layout\LayoutHelper;
 use Joomla\CMS\Router\Route;
use Joomla\Utilities\ArrayHelper;

 /**
  * Foo HTML class.
@@ -88,6 +89,42 @@ public function association($fooid)
 			$html = LayoutHelper::render('joomla.content.associations', $items);
 		}

		return $html;
	}
	/**
	 * Show the featured/not-featured icon.
	 *
	 * @param   integer  $value      The featured value.
	 * @param   integer  $i          Id of the item.
	 * @param   boolean  $canChange  Whether the value can be changed or not.
	 *
	 * @return  string	The anchor tag to toggle featured/unfeatured foos.
	 *
	 * @since   __BUMP_VERSION__
	 */
	public function featured($value, $i, $canChange = true)
	{
		// Array of image, task, title, action
		$states = array(
			0 => array('unfeatured', 'foos.featured', 'COM_CONTACT_UNFEATURED', 'JGLOBAL_ITEM_FEATURE'),
			1 => array('featured', 'foos.unfeatured', 'JFEATURED', 'JGLOBAL_ITEM_UNFEATURE'),
		);
		$state = ArrayHelper::getValue($states, (int) $value, $states[1]);
		$icon = $state[0] === 'featured' ? 'star featured' : 'star';

		if ($canChange)
		{
			$html = '<a href="#" onclick="return Joomla.listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="tbody-icon'
				. ($value == 1 ? ' active' : '') . '" aria-labelledby="cb' . $i . '-desc">'
				. '<span class="fas fa-' . $icon . '" aria-hidden="true"></span></a>'
				. '<div role="tooltip" id="cb' . $i . '-desc">' . Text::_($state[3]);
		}
		else
		{
			$html = '<a class="tbody-icon disabled' . ($value == 1 ? ' active' : '')
				. '" title="' . Text::_($state[2]) . '"><span class="fas fa-' . $icon . '" aria-hidden="true"></span></a>';
		}

 		return $html;
 	}
 }
diff --git a/src/administrator/components/com_foos/src/View/Foos/HtmlView.php b/src/administrator/components/com_foos/src/View/Foos/HtmlView.php
index 622ff2db..170a4115 100644
-- a/src/administrator/components/com_foos/src/View/Foos/HtmlView.php
++ b/src/administrator/components/com_foos/src/View/Foos/HtmlView.php
@@ -164,6 +164,16 @@ protected function addToolbar()
 			$childBar = $dropdown->getChildToolbar();
 			$childBar->publish('foos.publish')->listCheck(true);
 			$childBar->unpublish('foos.unpublish')->listCheck(true);

			$childBar->standardButton('featured')
				->text('JFEATURE')
				->task('foos.featured')
				->listCheck(true);
			$childBar->standardButton('unfeatured')
				->text('JUNFEATURE')
				->task('foos.unfeatured')
				->listCheck(true);

 			$childBar->archive('foos.archive')->listCheck(true);

 			if ($user->authorise('core.admin'))
diff --git a/src/administrator/components/com_foos/tmpl/foo/edit.php b/src/administrator/components/com_foos/tmpl/foo/edit.php
index e1dddc2e..5aae7519 100644
-- a/src/administrator/components/com_foos/tmpl/foo/edit.php
++ b/src/administrator/components/com_foos/tmpl/foo/edit.php
@@ -50,6 +50,7 @@
 						<?php echo $this->getForm()->renderField('publish_down'); ?>
 						<?php echo $this->getForm()->renderField('catid'); ?>
 						<?php echo $this->getForm()->renderField('language'); ?>
						<?php echo $this->getForm()->renderField('featured'); ?>
 					</div>
 				</div>
 			</div>
diff --git a/src/administrator/components/com_foos/tmpl/foos/default.php b/src/administrator/components/com_foos/tmpl/foos/default.php
index 3aa053c4..0b25a3b3 100644
-- a/src/administrator/components/com_foos/tmpl/foos/default.php
++ b/src/administrator/components/com_foos/tmpl/foos/default.php
@@ -57,6 +57,9 @@
 								<th scope="col" style="width:1%" class="text-center d-none d-md-table-cell">
 									<?php echo HTMLHelper::_('searchtools.sort', 'COM_FOOS_TABLE_TABLEHEAD_NAME', 'a.name', $listDirn, $listOrder); ?>
 								</th>
								<th scope="col" style="width:1%" class="text-center">
									<?php echo HTMLHelper::_('searchtools.sort', 'JFEATURED', 'a.featured', $listDirn, $listOrder); ?>
								</th>
 								<th scope="col" style="width:10%" class="d-none d-md-table-cell">
 									<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ACCESS', 'access_level', $listDirn, $listOrder); ?>
 								</th>
@@ -123,14 +126,17 @@
 									</div>
 								</th>
 								<td class="text-center">
									<?php
									echo HTMLHelper::_('jgrid.published', $item->published, $i, 'foos.', $canChange, 'cb', $item->publish_up, $item->publish_down);
									?>
									<?php echo HTMLHelper::_('foosadministrator.featured', $item->featured, $i, $canChange); ?>
 								</td>
 								<td class="small d-none d-md-table-cell">
 									<?php echo $item->access_level; ?>
 								</td>
								<td class="text-center">
									<?php
									echo HTMLHelper::_('jgrid.published', $item->published, $i, 'foos.', $canChange, 'cb', $item->publish_up, $item->publish_down);
									?>

								</td>
 								<?php if ($assoc) : ?>
 								<td class="d-none d-md-table-cell">
 									<?php if ($item->association) : ?>
diff --git a/src/components/com_foos/src/Model/FeaturedModel.php b/src/components/com_foos/src/Model/FeaturedModel.php
new file mode 100644
index 00000000..209aa9f4
-- /dev/null
++ b/src/components/com_foos/src/Model/FeaturedModel.php
@@ -0,0 +1,199 @@
<?php
/**
* @package     Joomla.Site
* @subpackage  com_foos
*
* @copyright   Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license     GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace FooNamespace\Component\Foos\Site\Model;

\defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\ParameterType;
use Joomla\Registry\Registry;

/**
* Featured foos model class.
*
* @since  __BUMP_VERSION__
*/
class FeaturedModel extends ListModel
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @since   __BUMP_VERSION__
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a list of items.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		// Invoke the parent getItems method to get the main list
		$items = parent::getItems();

		// Convert the params field into an object, saving original in _params
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item = &$items[$i];

			if (!isset($this->_params))
			{
				$item->params = new Registry($item->params);
			}
		}

		return $items;
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string    An SQL query
	 *
	 * @since   __BUMP_VERSION__
	 */
	protected function getListQuery()
	{
		$user = Factory::getUser();
		$groups = $user->getAuthorisedViewLevels();

		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Select required fields from the categories.
		$query->select($this->getState('list.select', 'a.*'))
			->from($db->quoteName('#__foos_details', 'a'))
			->where($db->quoteName('a.featured') . ' = 1')
			->whereIn($db->quoteName('a.access'), $groups)
			->innerJoin($db->quoteName('#__categories', 'c') . ' ON c.id = a.catid')
			->whereIn($db->quoteName('c.access'), $groups);

		// Filter by category.
		if ($categoryId = $this->getState('category.id'))
		{
			$query->where($db->quoteName('a.catid') . ' = :catid');
			$query->bind(':catid', $categoryId, ParameterType::INTEGER);
		}

		$query->select('c.published as cat_published, c.published AS parents_published')
			->where('c.published = 1');

		// Filter by state
		$state = $this->getState('filter.published');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('a.published') . ' = :published');
			$query->bind(':published', $state, ParameterType::INTEGER);

			// Filter by start and end dates.
			$nowDate = Factory::getDate()->toSql();

			$query->where('(' . $db->quoteName('a.publish_up') .
				' IS NULL OR ' . $db->quoteName('a.publish_up') . ' <= :publish_up)'
			)
				->where('(' . $db->quoteName('a.publish_down') .
					' IS NULL OR ' . $db->quoteName('a.publish_down') . ' >= :publish_down)'
				)
				->bind(':publish_up', $nowDate)
				->bind(':publish_down', $nowDate);
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$language = [Factory::getLanguage()->getTag(), '*'];
			$query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
		}

		// Add the list ordering clause.
		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	/**
	 * 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   __BUMP_VERSION__
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = Factory::getApplication();
		$params = ComponentHelper::getParams('com_foos');

		// List state information
		$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
		$this->setState('list.limit', $limit);

		$limitstart = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $limitstart);

		$orderCol = $app->input->get('filter_order', 'ordering');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->input->get('filter_order_Dir', 'ASC');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$user = Factory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_foos')) && (!$user->authorise('core.edit', 'com_foos')))
		{
			// Limit to published for people who can't edit or edit.state.
			$this->setState('filter.published', 1);

			// Filter by start and end dates.
			$this->setState('filter.publish_date', true);
		}

		$this->setState('filter.language', Multilanguage::isEnabled());

		// Load the parameters.
		$this->setState('params', $params);
	}
}
diff --git a/src/components/com_foos/src/View/Featured/HtmlView.php b/src/components/com_foos/src/View/Featured/HtmlView.php
new file mode 100644
index 00000000..e18572d0
-- /dev/null
++ b/src/components/com_foos/src/View/Featured/HtmlView.php
@@ -0,0 +1,200 @@
<?php
/**
* @package     Joomla.Site
* @subpackage  com_foos
*
* @copyright   Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license     GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace FooNamespace\Component\Foos\Site\View\Featured;

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\MVC\View\GenericDataException;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;

/**
* Featured View class
*
* @since  __BUMP_VERSION__
*/
class HtmlView extends BaseHtmlView
{
	/**
	 * The item model state
	 *
	 * @var    \Joomla\Registry\Registry
	 * @since  __BUMP_VERSION__
	 */
	protected $state;

	/**
	 * The item details
	 *
	 * @var    \JObject
	 * @since  __BUMP_VERSION__
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var    \JPagination
	 * @since  __BUMP_VERSION__
	 */
	protected $pagination;

	/**
	 * The page parameters
	 *
	 * @var    \Joomla\Registry\Registry|null
	 * @since  __BUMP_VERSION__
	 */
	protected $params = null;

	/**
	 * The page class suffix
	 *
	 * @var    string
	 * @since  __BUMP_VERSION__
	 */
	protected $pageclass_sfx = '';

	/**
	 * Method to display the view.
	 *
	 * @param   string  $tpl  The name of the template file to parse; automatically searches through the template paths.
	 *
	 * @return  mixed  \Exception on failure, void on success.
	 *
	 * @since   __BUMP_VERSION__
	 */
	public function display($tpl = null)
	{
		$app    = Factory::getApplication();
		$params = $app->getParams();

		// Get some data from the models
		$state      = $this->get('State');
		$items      = $this->get('Items');
		$category   = $this->get('Category');
		$children   = $this->get('Children');
		$parent     = $this->get('Parent');
		$pagination = $this->get('Pagination');

		// Flag indicates to not add limitstart=0 to URL
		$pagination->hideEmptyLimitstart = true;

		// Check for errors.
		if (count($errors = $this->get('Errors')))
		{
			throw new GenericDataException(implode("\n", $errors), 500);
		}

		// Prepare the data.
		// Compute the foos slug.
		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item       = &$items[$i];
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$temp       = $item->params;
			$item->params = clone $params;
			$item->params->merge($temp);

			if ($item->params->get('show_email', 0) == 1)
			{
				$item->email_to = trim($item->email_to);

				if (!empty($item->email_to) && MailHelper::isEmailAddress($item->email_to))
				{
					$item->email_to = HTMLHelper::_('email.cloak', $item->email_to);
				}
				else
				{
					$item->email_to = '';
				}
			}
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx'), ENT_COMPAT, 'UTF-8');

		$maxLevel         = $params->get('maxLevel', -1);
		$this->maxLevel   = &$maxLevel;
		$this->state      = &$state;
		$this->items      = &$items;
		$this->category   = &$category;
		$this->children   = &$children;
		$this->params     = &$params;
		$this->parent     = &$parent;
		$this->pagination = &$pagination;

		$this->_prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   __BUMP_VERSION__
	 */
	protected function _prepareDocument()
	{
		$app   = Factory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		// Because the application sets a default page title,
		// we need to get it from the menu item itself
		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', Text::_('COM_FOOS_DEFAULT_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

		if (empty($title))
		{
			$title = $app->get('sitename');
		}
		elseif ($app->get('sitename_pagetitles', 0) == 1)
		{
			$title = Text::sprintf('JPAGETITLE', $app->get('sitename'), $title);
		}
		elseif ($app->get('sitename_pagetitles', 0) == 2)
		{
			$title = Text::sprintf('JPAGETITLE', $title, $app->get('sitename'));
		}

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetaData('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetaData('robots', $this->params->get('robots'));
		}
	}
}
diff --git a/src/components/com_foos/tmpl/featured/default.php b/src/components/com_foos/tmpl/featured/default.php
new file mode 100644
index 00000000..23874326
-- /dev/null
++ b/src/components/com_foos/tmpl/featured/default.php
@@ -0,0 +1,33 @@
<?php
/**
* @package     Joomla.Site
* @subpackage  com_foos
*
* @copyright   Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license     GNU General Public License version 2 or later; see LICENSE.txt
*/

\defined('_JEXEC') or die;

?>
<div class="com-foos-featured blog-featured">
<?php if ($this->params->get('show_page_headings') != 0 ) : ?>
	<h1>
		<?php echo $this->escape($this->params->get('page_heading')); ?>
	</h1>
<?php endif; ?>

<?php echo $this->loadTemplate('items'); ?>

<?php if ($this->params->def('show_pagination', 2) == 1  || ($this->params->get('show_pagination') == 2 && $this->pagination->pagesTotal > 1)) : ?>
	<div class="com-foos-featured__pagination w-100">
		<?php if ($this->params->def('show_pagination_results', 1)) : ?>
			<p class="counter float-right pt-3 pr-2">
				<?php echo $this->pagination->getPagesCounter(); ?>
			</p>
		<?php endif; ?>

		<?php echo $this->pagination->getPagesLinks(); ?>
	</div>
<?php endif; ?>
</div>
diff --git a/src/components/com_foos/tmpl/featured/default.xml b/src/components/com_foos/tmpl/featured/default.xml
new file mode 100644
index 00000000..79f5ddf5
-- /dev/null
++ b/src/components/com_foos/tmpl/featured/default.xml
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>

<metadata>
	<layout title="COM_FOOS_FEATURED_VIEW_DEFAULT_TITLE">
		<help
			key = "JHELP_MENUS_MENU_ITEM_FOOS_FEATURED"
		/>
		<message>
			<![CDATA[COM_FOOS_FEATURED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">

				<field
					name="spacer"
					type="spacer"
					label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
					class="text"
				/>

				<field
					name="show_headings"
					type="list"
					label="JGLOBAL_SHOW_HEADINGS_LABEL"
					useglobal="true"
					class="custom-select-color-state"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_pagination"
					type="list"
					label="JGLOBAL_PAGINATION_LABEL"
					useglobal="true"
					class="custom-select-color-state"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
					<option value="2">JGLOBAL_AUTO</option>
				</field>
		</fieldset>
	</fields>
</metadata>
diff --git a/src/components/com_foos/tmpl/featured/default_items.php b/src/components/com_foos/tmpl/featured/default_items.php
new file mode 100644
index 00000000..ffc219bc
-- /dev/null
++ b/src/components/com_foos/tmpl/featured/default_items.php
@@ -0,0 +1,66 @@
<?php
/**
* @package     Joomla.Site
* @subpackage  com_foos
*
* @copyright   Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @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\Uri\Uri;

HTMLHelper::_('behavior.core');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

// Create a shortcut for params.
$params = &$this->item->params;
?>

<div class="com-foos-featured__items">
	<?php if (empty($this->items)) : ?>
		<p class="com-foos-featured__message"> <?php echo Text::_('COM_FOO_NO_FOOS'); ?>	 </p>
	<?php else : ?>

	<form action="<?php echo htmlspecialchars(Uri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
		<table class="com-foos-featured__table table">
			<?php if ($this->params->get('show_headings')) : ?>
			<thead class="thead-default">
				<tr>
					<th class="item-num">
						<?php echo Text::_('JGLOBAL_NUM'); ?>
					</th>

					<th class="item-title">
						<?php echo HTMLHelper::_('grid.sort', 'COM_FOO_FOO_EMAIL_NAME_LABEL', 'a.name', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<?php endif; ?>

			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="<?php echo ($i % 2) ? 'odd' : 'even'; ?>" itemscope itemtype="https://schema.org/Person">
						<td class="item-num">
							<?php echo $i; ?>
						</td>

						<td class="item-title">
							<?php if ($this->items[$i]->published == 0) : ?>
								<span class="badge badge-warning"><?php echo Text::_('JUNPUBLISHED'); ?></span>
							<?php endif; ?>
								<span itemprop="name"><?php echo $item->name; ?></span>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>

	</form>
	<?php endif; ?>
</div>

Schritt für Schritt

Neue Dateien

src/administrator/components/com_foos/sql/updates/mysql/24.0.0.sql

src/administrator/components/com_foos/sql/updates/mysql/24.0.0.sql

ALTER TABLE `#__foos_details` ADD COLUMN  `featured` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT 'Set if contact is featured.';
ALTER TABLE `#__foos_details` ADD KEY `idx_featured_catid` (`featured`,`catid`);

src/components/com_foos/src/Model/FeaturedModel.php

Um die Daten, die featured sind zu holfen, erstellen wir ein eigenes Model.

src/components/com_foos/src/Model/FeaturedModel.php

<?php
namespace FooNamespace\Component\Foos\Site\Model;

\defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\ParameterType;
use Joomla\Registry\Registry;

class FeaturedModel extends ListModel
{
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id', 'a.id',
				'name', 'a.name',
				'ordering', 'a.ordering',
			);
		}

		parent::__construct($config);
	}

	public function getItems()
	{
		$items = parent::getItems();

		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item = &$items[$i];

			if (!isset($this->_params))
			{
				$item->params = new Registry($item->params);
			}
		}

		return $items;
	}

	protected function getListQuery()
	{
		$user = Factory::getUser();
		$groups = $user->getAuthorisedViewLevels();

		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select($this->getState('list.select', 'a.*'))
			->from($db->quoteName('#__foos_details', 'a'))
			->where($db->quoteName('a.featured') . ' = 1')
			->whereIn($db->quoteName('a.access'), $groups)
			->innerJoin($db->quoteName('#__categories', 'c') . ' ON c.id = a.catid')
			->whereIn($db->quoteName('c.access'), $groups);

		if ($categoryId = $this->getState('category.id'))
		{
			$query->where($db->quoteName('a.catid') . ' = :catid');
			$query->bind(':catid', $categoryId, ParameterType::INTEGER);
		}

		$query->select('c.published as cat_published, c.published AS parents_published')
			->where('c.published = 1');

		$state = $this->getState('filter.published');

		if (is_numeric($state))
		{
			$query->where($db->quoteName('a.published') . ' = :published');
			$query->bind(':published', $state, ParameterType::INTEGER);

			$nowDate = Factory::getDate()->toSql();

			$query->where('(' . $db->quoteName('a.publish_up') .
				' IS NULL OR ' . $db->quoteName('a.publish_up') . ' <= :publish_up)'
			)
				->where('(' . $db->quoteName('a.publish_down') .
					' IS NULL OR ' . $db->quoteName('a.publish_down') . ' >= :publish_down)'
				)
				->bind(':publish_up', $nowDate)
				->bind(':publish_down', $nowDate);
		}

		if ($this->getState('filter.language'))
		{
			$language = [Factory::getLanguage()->getTag(), '*'];
			$query->whereIn($db->quoteName('a.language'), $language, ParameterType::STRING);
		}

		$query->order($db->escape($this->getState('list.ordering', 'a.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));

		return $query;
	}

	protected function populateState($ordering = null, $direction = null)
	{
		$app = Factory::getApplication();
		$params = ComponentHelper::getParams('com_foos');

		$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
		$this->setState('list.limit', $limit);

		$limitstart = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $limitstart);

		$orderCol = $app->input->get('filter_order', 'ordering');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'ordering';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->input->get('filter_order_Dir', 'ASC');

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$user = Factory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_foos')) && (!$user->authorise('core.edit', 'com_foos')))
		{
			$this->setState('filter.published', 1);

			$this->setState('filter.publish_date', true);
		}

		$this->setState('filter.language', Multilanguage::isEnabled());

		$this->setState('params', $params);
	}
}

src/components/com_foos/src/View/Featured/HtmlView.php

featured bekommt eine eigen Datei zur Verwaltung der Anzeige im Frontend.

src/components/com_foos/src/View/Featured/HtmlView.php

<?php

namespace FooNamespace\Component\Foos\Site\View\Featured;

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\MVC\View\GenericDataException;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;

class HtmlView extends BaseHtmlView
{
	protected $state;

	protected $items;

	protected $pagination;

	protected $params = null;

	protected $pageclass_sfx = '';

	public function display($tpl = null)
	{
		$app    = Factory::getApplication();
		$params = $app->getParams();

		$state      = $this->get('State');
		$items      = $this->get('Items');
		$category   = $this->get('Category');
		$children   = $this->get('Children');
		$parent     = $this->get('Parent');
		$pagination = $this->get('Pagination');

		$pagination->hideEmptyLimitstart = true;

		if (count($errors = $this->get('Errors')))
		{
			throw new GenericDataException(implode("\n", $errors), 500);
		}

		for ($i = 0, $n = count($items); $i < $n; $i++)
		{
			$item       = &$items[$i];
			$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$temp       = $item->params;
			$item->params = clone $params;
			$item->params->merge($temp);

			if ($item->params->get('show_email', 0) == 1)
			{
				$item->email_to = trim($item->email_to);

				if (!empty($item->email_to) && MailHelper::isEmailAddress($item->email_to))
				{
					$item->email_to = HTMLHelper::_('email.cloak', $item->email_to);
				}
				else
				{
					$item->email_to = '';
				}
			}
		}

		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx'), ENT_COMPAT, 'UTF-8');

		$maxLevel         = $params->get('maxLevel', -1);
		$this->maxLevel   = &$maxLevel;
		$this->state      = &$state;
		$this->items      = &$items;
		$this->category   = &$category;
		$this->children   = &$children;
		$this->params     = &$params;
		$this->parent     = &$parent;
		$this->pagination = &$pagination;

		$this->_prepareDocument();

		return parent::display($tpl);
	}

	protected function _prepareDocument()
	{
		$app   = Factory::getApplication();
		$menus = $app->getMenu();
		$title = null;

		$menu = $menus->getActive();

		if ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
		}
		else
		{
			$this->params->def('page_heading', Text::_('COM_FOOS_DEFAULT_PAGE_TITLE'));
		}

		$title = $this->params->get('page_title', '');

		if (empty($title))
		{
			$title = $app->get('sitename');
		}
		elseif ($app->get('sitename_pagetitles', 0) == 1)
		{
			$title = Text::sprintf('JPAGETITLE', $app->get('sitename'), $title);
		}
		elseif ($app->get('sitename_pagetitles', 0) == 2)
		{
			$title = Text::sprintf('JPAGETITLE', $title, $app->get('sitename'));
		}

		$this->document->setTitle($title);

		if ($this->params->get('menu-meta_description'))
		{
			$this->document->setDescription($this->params->get('menu-meta_description'));
		}

		if ($this->params->get('menu-meta_keywords'))
		{
			$this->document->setMetaData('keywords', $this->params->get('menu-meta_keywords'));
		}

		if ($this->params->get('robots'))
		{
			$this->document->setMetaData('robots', $this->params->get('robots'));
		}
	}
}

src/components/com_foos/tmpl/featured/default.php

src/components/com_foos/tmpl/featured/default.php

<?php
\defined('_JEXEC') or die;
?>
<div class="com-foos-featured blog-featured">
<?php if ($this->params->get('show_page_headings') != 0 ) : ?>
	<h1>
		<?php echo $this->escape($this->params->get('page_heading')); ?>
	</h1>
<?php endif; ?>

<?php echo $this->loadTemplate('items'); ?>

<?php if ($this->params->def('show_pagination', 2) == 1  || ($this->params->get('show_pagination') == 2 && $this->pagination->pagesTotal > 1)) : ?>
	<div class="com-foos-featured__pagination w-100">
		<?php if ($this->params->def('show_pagination_results', 1)) : ?>
			<p class="counter float-right pt-3 pr-2">
				<?php echo $this->pagination->getPagesCounter(); ?>
			</p>
		<?php endif; ?>

		<?php echo $this->pagination->getPagesLinks(); ?>
	</div>
<?php endif; ?>
</div>

src/components/com_foos/tmpl/featured/default.xml

Die XML-Datei benötigen wir, damit im Frontend die Anzeige der featured Elemente über einen Menüpunkt möglich ist.

src/components/com_foos/tmpl/featured/default.xml

<?xml version="1.0" encoding="utf-8"?>

<metadata>
	<layout title="COM_FOOS_FEATURED_VIEW_DEFAULT_TITLE">
		<help
			key = "JHELP_MENUS_MENU_ITEM_FOOS_FEATURED"
		/>
		<message>
			<![CDATA[COM_FOOS_FEATURED_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>

	<fields name="params">
		<fieldset name="advanced" label="JGLOBAL_LIST_LAYOUT_OPTIONS">

				<field
					name="spacer"
					type="spacer"
					label="JGLOBAL_SUBSLIDER_DRILL_CATEGORIES_LABEL"
					class="text"
				/>

				<field
					name="show_headings"
					type="list"
					label="JGLOBAL_SHOW_HEADINGS_LABEL"
					useglobal="true"
					class="custom-select-color-state"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field
					name="show_pagination"
					type="list"
					label="JGLOBAL_PAGINATION_LABEL"
					useglobal="true"
					class="custom-select-color-state"
					>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
					<option value="2">JGLOBAL_AUTO</option>
				</field>
		</fieldset>
	</fields>
</metadata>

src/components/comfoos/tmpl/featured/defaultitems.php

src/components/comfoos/tmpl/featured/defaultitems.php

<?php
\defined('_JEXEC') or die;

use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;

HTMLHelper::_('behavior.core');

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn  = $this->escape($this->state->get('list.direction'));

$params = &$this->item->params;
?>

<div class="com-foos-featured__items">
	<?php if (empty($this->items)) : ?>
		<p class="com-foos-featured__message"> <?php echo Text::_('COM_FOO_NO_FOOS'); ?>	 </p>
	<?php else : ?>

	<form action="<?php echo htmlspecialchars(Uri::getInstance()->toString()); ?>" method="post" name="adminForm" id="adminForm">
		<table class="com-foos-featured__table table">
			<?php if ($this->params->get('show_headings')) : ?>
			<thead class="thead-default">
				<tr>
					<th class="item-num">
						<?php echo Text::_('JGLOBAL_NUM'); ?>
					</th>

					<th class="item-title">
						<?php echo HTMLHelper::_('grid.sort', 'COM_FOO_FOO_EMAIL_NAME_LABEL', 'a.name', $listDirn, $listOrder); ?>
					</th>
				</tr>
			</thead>
			<?php endif; ?>

			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
					<tr class="<?php echo ($i % 2) ? 'odd' : 'even'; ?>" itemscope itemtype="https://schema.org/Person">
						<td class="item-num">
							<?php echo $i; ?>
						</td>

						<td class="item-title">
							<?php if ($this->items[$i]->published == 0) : ?>
								<span class="badge badge-warning"><?php echo Text::_('JUNPUBLISHED'); ?></span>
							<?php endif; ?>
								<span itemprop="name"><?php echo $item->name; ?></span>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>

	</form>
	<?php endif; ?>
</div>

Geänderte Dateien

src/administrator/components/com_foos/forms/foo.xml

...
<field
  name="featured"
  type="radio"
  class="switcher"
  label="JFEATURED"
  default="0"
  >
  <option value="0">JNO</option>
  <option value="1">JYES</option>
</field>
...

src/administrator/components/com_foos/sql/install.mysql.utf8.sql

src/administrator/components/com_foos/sql/install.mysql.utf8.sql

...
ALTER TABLE `#__foos_details` ADD COLUMN  `featured` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT 'Set if contact is featured.';
ALTER TABLE `#__foos_details` ADD KEY `idx_featured_catid` (`featured`,`catid`);

src/administrator/components/com_foos/src/Controller/FoosController.php

Wir implementieren die Funktion im FoosController, mit der wir die Eigenschaft featured setzen.

src/administrator/components/com_foos/src/Controller/FoosController.php

...
public function __construct($config = array(), MVCFactoryInterface $factory = null, $app = null, $input = null)
{
  parent::__construct($config, $factory, $app, $input);

  $this->registerTask('unfeatured', 'featured');
}
...
...
public function featured()
{
  $this->checkToken();

  $ids    = $this->input->get('cid', array(), 'array');
  $values = array('featured' => 1, 'unfeatured' => 0);
  $task   = $this->getTask();
  $value  = ArrayHelper::getValue($values, $task, 0, 'int');

  $model  = $this->getModel();

  foreach ($ids as $i => $id)
  {
    $item = $model->getItem($id);

    if (!$this->app->getIdentity()->authorise('core.edit.state', 'com_foos.category.' . (int) $item->catid))
    {
      unset($ids[$i]);
      $this->app->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'notice');
    }
  }

  if (empty($ids))
  {
    $this->app->enqueueMessage(Text::_('COM_FOOS_NO_ITEM_SELECTED'), 'warning');
  }
  else
  {
    if (!$model->featured($ids, $value))
    {
      $this->app->enqueueMessage($model->getError(), 'warning');
    }

    if ($value == 1)
    {
      $message = Text::plural('COM_FOOS_N_ITEMS_FEATURED', count($ids));
    }
    else
    {
      $message = Text::plural('COM_FOOS_N_ITEMS_UNFEATURED', count($ids));
    }
  }

  $this->setRedirect('index.php?option=com_foos&view=foos', $message);
}
...

src/administrator/components/com_foos/src/Model/FooModel.php

Im Model eines Elementes implementieren wir die Methode, mit der die Eigenschaft featured verändert wird.

src/administrator/components/com_foos/src/Model/FooModel.php

	public function featured($pks, $value = 0)
	{
		$pks = ArrayHelper::toInteger((array) $pks);

		if (empty($pks))
		{
			$this->setError(Text::_('COM_FOOS_NO_ITEM_SELECTED'));

			return false;
		}

		$table = $this->getTable();

		try
		{
			$db = $this->getDbo();

			$query = $db->getQuery(true);
			$query->update($db->quoteName('#__foos_details'));
			$query->set($db->quoteName('featured') . ' = :featured');
			$query->whereIn($db->quoteName('id'), $pks);
			$query->bind(':featured', $value, ParameterType::INTEGER);

			$db->setQuery($query);

			$db->execute();
		}
		catch (\Exception $e)
		{
			$this->setError($e->getMessage());

			return false;
		}

		$table->reorder();

		$this->cleanCache();

		return true;
	}

src/administrator/components/com_foos/src/Model/FoosModel.php

Im Model erledigen wir die notwendigen Anpassungen bei der Datenbankabfrage.

src/administrator/components/com_foos/src/Model/FoosModel.php

...
$featured = (string) $this->getState('filter.featured');

if (in_array($featured, ['0','1']))
{
  $query->where($db->quoteName('a.featured') . ' = ' . (int) $featured);
}
...

src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php

Im machen wir es möglich, die Eigenschaft auch in der Übersichtsliste per Klick auf das Stern-Symbol zu verändern.

src/administrator/components/com_foos/src/Service/HTML/AdministratorService.php

...
public function featured($value, $i, $canChange = true)
{
  $states = array(
    0 => array('unfeatured', 'contacts.featured', 'COM_CONTACT_UNFEATURED', 'JGLOBAL_ITEM_FEATURE'),
    1 => array('featured', 'contacts.unfeatured', 'JFEATURED', 'JGLOBAL_ITEM_UNFEATURE'),
  );
  $state = ArrayHelper::getValue($states, (int) $value, $states[1]);
  $icon = $state[0] === 'featured' ? 'star featured' : 'star';

  if ($canChange)
  {
    $html = '<a href="#" onclick="return Joomla.listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="tbody-icon'
      . ($value == 1 ? ' active' : '') . '" aria-labelledby="cb' . $i . '-desc">'
      . '<span class="fas fa-' . $icon . '" aria-hidden="true"></span></a>'
      . '<div role="tooltip" id="cb' . $i . '-desc">' . Text::_($state[3]);
  }
  else
  {
    $html = '<a class="tbody-icon disabled' . ($value == 1 ? ' active' : '')
      . '" title="' . Text::_($state[2]) . '"><span class="fas fa-' . $icon . '" aria-hidden="true"></span></a>';
  }

  return $html;
}
...

src/administrator/components/com_foos/src/View/Foos/HtmlView.php

Wir ergänzen die Werkzeugleiste. Featured soll auch hier über eine Aktion aktiviert werden.

src/administrator/components/com_foos/src/View/Foos/HtmlView.php

...
$childBar->standardButton('featured')
  ->text('JFEATURE')
  ->task('foos.featured')
  ->listCheck(true);
$childBar->standardButton('unfeatured')
  ->text('JUNFEATURE')
  ->task('foos.unfeatured')
  ->listCheck(true);
...

src/administrator/components/com_foos/tmpl/foo/edit.php

Im Formular zum Anlegen oder Edieren eines Elementes fügen wir den Befehl ein, der mithilfe der XML Datei ein Feld erstellt.

https://github.com/astridx/boilerplate/blob/3fd0e4d60c63c61c35c8f58040f55e1a38059c66/src/administrator/components/com_foos/tmpl/foo/edit.php

...
<?php echo $this->getForm()->renderField('featured'); ?>
...

src/administrator/components/com_foos/tmpl/foos/default.php

In der Übersicht fügen wir eine Spalte ein, in der der Zustand mit einem ausgefüllten oder leeren Stern angezeigt wird und per Klick geändert werden kann. HTMLHelper übernimmt die meister Arbeit für uns.

src/administrator/components/com_foos/tmpl/foos/default.php

...
<th scope="col" style="width:1%" class="text-center">
  <?php echo HTMLHelper::_('searchtools.sort', 'JFEATURED', 'a.featured', $listDirn, $listOrder); >
</th>
...
...
<?php echo HTMLHelper::_('foosadministrator.featured', $item->featured, $i, $canChange); ?>
...

src/components/com_foos/src/Model/FeaturedModel.php

Teste deine Joomla-Komponente

  1. Installiere deine Komponente in Joomla! Version 4, um sie zu testen:

Kopiere die Dateien im administrator Ordner in den administrator Ordner deiner Joomla! 4 Installation.
Kopiere die Dateien im components Ordner in den components Ordner deiner Joomla! 4 Installation.
Kopiere die Dateien im media Ordner in den media Ordner deiner Joomla! 4 Installation.

  1. Die Datenbank ist geändert worden, so dass es erforderlich ist, sie zu aktualisieren. Öffne den Bereich System | Information | Database, wie in Teil 16 beschrieben. Wähle deine Komponente aus und klicke auf Update Structure.

Joomla! Published

  1. Öffne die Ansicht deiner Komponente im Administrationsbereich. Die Liste enthält eine Spalte die mit featured überschrieben ist.

Joomla! Featured

  1. Öffne ein Item in der Bearbeitungsansicht und überzeuge dich davon, dass du hier das Attribut featured zum Bearbeiten angeboten bekommst.

Joomla! Featured

  1. Lege einen Menüpunkt vom Type featured an.

Joomla! Featured

  1. Wechsele ins Frontend und stelle sicher, dass unter dem Menüpunkt featured ausschließlich Items angezeigt werden, bei denen das Attribut gesetzt ist und bei denen die zugehörige Kategorie ebenfalls veröffentlicht ist.

Joomla! Featured

Geänderte Dateien

Übersicht

Vor oder zurück ...