If you worked with Joomla, you know it from other components: Items have a status that can be changed. This section shows you how to
- unpublish,
- publish,
- schedule,
- archive and
- trash items.
For impatient people: View the changed program code in the Diff View[^codeberg.org/astrid/j4examplecode/compare/t13...t12] and copy these changes into your development version.
Step by step
New files
administrator/components/com_foos/sql/updates/mysql/13.0.0.sql
In case of an update, the database is updated to the latest version for version 13 using the file administrator/components/com_foos/sql/updates/mysql/13.0.0.sql
. Specifically, columns are added for saving the data for publication.
administrator/components/com_foos/sql/updates/mysql/13.0.0.sql
<!-- https://codeberg.org/astrid/j4examplecode/raw/branch/t13/src/administrator/components/com_foos/sql/updates/mysql/13.0.0.sql -->
ALTER TABLE `#__foos_details` ADD COLUMN `published` tinyint(1) NOT NULL DEFAULT 0 AFTER `alias`;
ALTER TABLE `#__foos_details` ADD COLUMN `publish_up` datetime AFTER `alias`;
ALTER TABLE `#__foos_details` ADD COLUMN `publish_down` datetime AFTER `alias`;
ALTER TABLE `#__foos_details` ADD KEY `idx_state` (`published`);
administrator/components/com_foos/src/Controller/FoosController.php
Now Joomla needs the class AdminController
. Therefore, we create the class FoosController
, which inherits from AdminController
. At the moment, FoosController
does not contain any implementations of its own. The controller only calls methods of the parent class.
administrator/components/com_foos/src/Controller/FoosController.php
<?php
// https://codeberg.org/astrid/j4examplecode/raw/branch/t13/src/administrator/components/com_foos/src/Controller/FoosController.php
<?php
/**
* @package Joomla.Administrator
* @subpackage com_foos
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace FooNamespace\Component\Foos\Administrator\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\MVC\Controller\AdminController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\Input\Input;
/**
* Foos list controller class.
*
* @since __BUMP_VERSION__
*/
class FoosController extends AdminController
{
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
* Recognized key values include 'name', 'default_task', 'model_path', and
* 'view_path' (this list is not meant to be comprehensive).
* @param MVCFactoryInterface $factory The factory.
* @param CMSApplication $app The JApplication for the dispatcher
* @param Input $input Input
*
* @since __BUMP_VERSION__
*/
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
{
parent::__construct($config, $factory, $app, $input);
}
/**
* Proxy for getModel.
*
* @param string $name The name of the model.
* @param string $prefix The prefix for the PHP class name.
* @param array $config Array of configuration parameters.
*
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel
*
* @since __BUMP_VERSION__
*/
public function getModel($name = 'Foo', $prefix = 'Administrator', $config = ['ignore_request' => true])
{
return parent::getModel($name, $prefix, $config);
}
}
Modified files
administrator/components/com_foos/forms/foo.xml
Three fields are added to the form. One, in which the status is set and two, through which a scheduled publication is achieved with the help of a calendar.
administrator/components/com_foos/forms/foo.xml
hint="JFIELD_ALIAS_PLACEHOLDER"
/>
<field
name="published"
type="list"
label="JSTATUS"
default="1"
id="published"
class="custom-select-color-state"
size="1"
>
<option value="1">JPUBLISHED</option>
<option value="0">JUNPUBLISHED</option>
<option value="2">JARCHIVED</option>
<option value="-2">JTRASHED</option>
</field>
<field
name="publish_up"
type="calendar"
label="COM_FOOS_FIELD_PUBLISH_UP_LABEL"
translateformat="true"
showtime="true"
size="22"
filter="user_utc"
/>
<field
name="publish_down"
type="calendar"
label="COM_FOOS_FIELD_PUBLISH_DOWN_LABEL"
translateformat="true"
showtime="true"
size="22"
filter="user_utc"
/>
<field
name="catid"
type="categoryedit"
administrator/components/com_foos/sql/install.mysql.utf8.sql
administrator/components/com_foos/sql/install.mysql.utf8.sql
is used in the case of a new installation to create the database. Therefore, we add the necessary information here. We had already added this in the file administrator/components/com_foos/sql/updates/mysql/13.0.0.sql
. This file is only used during an update.
administrator/components/com_foos/sql/install.mysql.utf8.sql
ALTER TABLE `#__foos_details` ADD COLUMN `access` int(10) unsigned NOT NULL DEF
ALTER TABLE `#__foos_details` ADD KEY `idx_access` (`access`);
ALTER TABLE `#__foos_details` ADD COLUMN `catid` int(11) NOT NULL DEFAULT 0 AFTER `alias`;
ALTER TABLE `#__foos_details` ADD COLUMN `state` tinyint(3) NOT NULL DEFAULT 0 AFTER `alias`;
ALTER TABLE `#__foos_details` ADD KEY `idx_catid` (`catid`);
ALTER TABLE `#__foos_details` ADD COLUMN `published` tinyint(1) NOT NULL DEFAULT 0 AFTER `alias`;
ALTER TABLE `#__foos_details` ADD COLUMN `publish_up` datetime AFTER `alias`;
ALTER TABLE `#__foos_details` ADD COLUMN `publish_down` datetime AFTER `alias`;
ALTER TABLE `#__foos_details` ADD KEY `idx_state` (`published`);
administrator/components/com_foos/src/Extension/FoosComponent.php
The component class receives the new function 'getStateColumnForSection'. This is used to show in the category view how many items are published or hidden. Remember. We introduced categories in the previous part. Then this part did not work in the category view. Now it is counted correctly. See for yourself after you have added this function to the component in Joomla.
administrator/components/com_foos/src/Extension/FoosComponent.php
protected function getTableNameForSection(string $section = null)
{
return ($section === 'category' ? 'categories' : 'foos_details');
}
protected function getStateColumnForSection(string $section = null)
{
return 'published';
}
}
administrator/components/com_foos/src/Model/FoosModel.php
We extend the model so that the information about the status is retrieved from the database when the list view is created for the backend.
administrator/components/com_foos/src/Model/FoosModel.php
protected function getListQuery()
// Select the required fields from the table.
$query->select(
$db->quoteName(['a.id', 'a.name', 'a.alias', 'a.access', 'a.catid'])
$db->quoteName(['a.id', 'a.name', 'a.alias', 'a.access', 'a.catid', 'a.published', 'a.publish_up', 'a.publish_down'])
);
$query->from($db->quoteName('#__foos_details', 'a'));
administrator/components/com_foos/src/Table/FooTable.php
In the file administrator/components/com_foos/src/Table/FooTable.php
, which manages the database table, we add checks. This way we make sure that no impossible data is stored.
We need store($updateNulls = true)
because the parent class Table
sets the variable $updateNulls
to false
. This causes form fields that hold the value null
not to be changed in the database. Most of the time this is correct. The most common case is probably that a value is not set from the beginning and has not been changed in the form when editing the element. Because an empty date field is stored in the database with null
, it is necessary in our case to force the storage of null
values. This is done by setting the variable $updateNulls
to true
.
administrator/components/com_foos/src/Table/FooTable.php
public function generateAlias()
return $this->alias;
}
public function check()
{
try {
parent::check();
} catch (\Exception $e) {
$this->setError($e->getMessage());
return false;
}
// Check the publish down date is not earlier than publish up.
if ($this->publish_down > $this->_db->getNullDate() && $this->publish_down < $this->publish_up) {
$this->setError(Text::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));
return false;
}
// Set publish_up, publish_down to null if not set
if (!$this->publish_up) {
$this->publish_up = null;
}
if (!$this->publish_down) {
$this->publish_down = null;
}
return true;
}
public function store($updateNulls = true)
{
return parent::store($updateNulls);
}
}
administrator/components/com_foos/tmpl/foo/edit.php
In the form for editing an element, we make sure that the new fields are rendered.
administrator/components/com_foos/tmpl/foo/edit.php
<?php echo $this->getForm()->renderField('alias'); ?>
<?php echo $this->getForm()->renderField('access'); ?>
<?php echo $this->getForm()->renderField('catid'); ?>
<?php echo $this->getForm()->renderField('published'); ?>
<?php echo $this->getForm()->renderField('publish_up'); ?>
<?php echo $this->getForm()->renderField('publish_down'); ?>
<input type="hidden" name="task" value="">
<?php echo HTMLHelper::_('form.token'); ?>
</form>
administrator/components/com_foos/tmpl/foos/default.php
Finally, we add to the overview list in the backend. We create a column for displaying the publication status.
Are you wondering about the the tags
<td>
and<th>
. This seems to be a mistake at first sight. But it is correct. You can find more information in the Github-Issue 24546 [^github.com/joomla/joomla-cms/pull/24546].
administrator/components/com_foos/tmpl/foos/default.php
<table class="table" id="fooList">
<thead>
<tr>
<td style="width:1%" class="text-center">
<?php echo HTMLHelper::_('grid.checkall'); ?>
</td>
<th scope="col" style="width:1%" class="text-center d-none d-md-table-cell">
<?php echo Text::_('COM_FOOS_TABLE_TABLEHEAD_NAME'); ?>
</th>
<th scope="col" style="width:1%; min-width:85px" class="text-center">
<?php echo TEXT::_('JSTATUS'); ?>
</th>
<th scope="col" style="width:10%" class="d-none d-md-table-cell">
<?php echo TEXT::_('JGRID_HEADING_ACCESS') ?>
</th>
foreach ($this->items as $i => $item) :
?>
<tr class="row<?php echo $i % 2; ?>">
<td class="text-center">
<?php echo HTMLHelper::_('grid.id', $i, $item->id); ?>
</td>
<th scope="row" class="has-context">
<div>
<?php echo $this->escape($item->name); ?>
<?php echo Text::_('JCATEGORY') . ': ' . $this->escape($item->category_title); ?>
</div>
</th>
<td class="text-center">
<?php
echo HTMLHelper::_('jgrid.published', $item->published, $i, 'foos.', true, 'cb', $item->publish_up, $item->publish_down);
?>
</td>
<td class="small d-none d-md-table-cell">
<?php echo $item->access_level; ?>
</td>
Test your Joomla component
-
install your component in Joomla version 4 to test it: Copy the files in the
administrator
folder to theadministrator
folder of your Joomla 4 installation. -
the database has been changed again, so it is necessary to update it. Uninstalling and reinstalling is time-consuming. That's why I'll tell you an easier method.
-
open the section 'System | Information | Database'.
-
select your component and click on 'Update Structure'. That was it! Now you have updated the database.
-
open the view of your component in the administration area and make sure that you see a column here that is overwritten with status. Click on an icon in it and change the status of the corresponding element from 'published' to 'hidden' and vice versa.
- open an element and check that the status is also editable in this view. It is also possible to specify a date, so that items are hidden or published according to the date.
Webmentions