431 lines
14 KiB
Markdown
431 lines
14 KiB
Markdown
# Depot
|
|
|
|
## Introduction
|
|
|
|
This project is also based on the desperation to sort and find my electronic
|
|
components. Some integrated circuits (ICs) accumulated in various boxes and
|
|
the question of whether I own that or the other IC, had to be painstakingly
|
|
researched. Above all, there were at one time several places where components
|
|
were stored or partly kept at a plant.
|
|
The idea was born, but it took long time to implement it.
|
|
Klosterneuburg, October 2023 Thomas Kuschel KW4NZ.
|
|
|
|
## Workflow (since 0.0.1)
|
|
|
|
In git we start to make a new branch named b1_basic_backend, where we start
|
|
developing our project. The first run with simply renaming entries from a
|
|
copy of the component **com_banners** did not work as expected.
|
|
So let us start at the very beginning:
|
|
|
|
### Adding basic files for component (b1_basic_backend)
|
|
|
|
With the git branch **b1_basic_backend**
|
|
Add the following basic six files:
|
|
|
|
1. admin
|
|
|
|
- src/Extension/DepotComponent.php: The main extension file for the component.
|
|
- services/provider.php: It tells Joomla how to initialize or boot the component.
|
|
- src/Controller/DisplayController.php: The default Controller for the component.
|
|
- src/View/Parts/HtmlView.php: The Html View for the "Parts" page.
|
|
- tmpl/parts/default.php: The layout file for the "Parts" page.
|
|
|
|
2. depot.xml: XML manifest file that tells Joomla! how to install the component.
|
|
|
|
#### Description of each file:
|
|
|
|
##### 1. DepotComponent.php
|
|
This file contains class for the extension. The class extends MVCComponent.
|
|
|
|
##### 2. provider.php
|
|
This is a special file that tells Joomla how to initialize the component - which
|
|
services it requires and how they should be provided.
|
|
|
|
The service provider file registers dependencies the component will use.
|
|
Here, we have included two dependencies:
|
|
|
|
- **DispatcherFactory** is needed to create the Dispatcher class instance,
|
|
and then Joomla will call dispatch() on this Dispatcher object, as the
|
|
next step in running the component.
|
|
|
|
- **MVCFactory** is needed to create the Controller, View, Model and Table class
|
|
instances on behalf of the component.
|
|
|
|
|
|
##### 3. DisplayController.php
|
|
This is a **default controller** for the component. It simply sets its default
|
|
view and leaves the rest to its parent.
|
|
|
|
When you view the component through URL, Joomla uses the **controller** to execute
|
|
the **task**. The task is the name of method in the controller file.
|
|
If you do not pass the controller or task in the URL, it defaults to Display
|
|
Controller and display Task.
|
|
|
|
The default view is the name of the component. So, here we need to override the
|
|
default view to `parts`.
|
|
|
|
##### 4. HtmlView.php
|
|
This file contains class HtmlView that extends BaseHtmlView. The BaseHtmlView is
|
|
the base class for a Joomla View.
|
|
|
|
The **view gets the data from the model to be output by the layout file.**
|
|
|
|
For example:
|
|
```php
|
|
$this->msg = $this->get('Msg');
|
|
```
|
|
|
|
This method converts the get('Msg') call into a getMsg() call on the model, which
|
|
is the method which you have to provide in the model.
|
|
|
|
The view file displays data using the template layout file - $tpl, which defaults
|
|
to default.php.
|
|
|
|
##### 5. default.php
|
|
This file holds the template for the page. When no specific layout is
|
|
requested for a view, Joomla will load the template in the **default.php** file.
|
|
|
|
```php
|
|
<h2>Welcome to Depot Component!</h2>
|
|
```
|
|
|
|
##### 6. depot.xml
|
|
This file tells Joomla how to install the component and what file are included.
|
|
|
|
In the administration part, we include a link to the menu and include files
|
|
and folders (services, src, tmpl and so on) which are in the parent folder
|
|
admin of the component. While installing the component, these will get copied
|
|
to the Joomla administrator/components/com_depot.
|
|
|
|
#### Installation the component
|
|
Create a **.zip** file of the com_depot directory. Then inside the Joomla
|
|
Administration upload this .zip package.
|
|
|
|
Now you should see a new link "Depot" in the "Compnents" section of the menu.
|
|
If you click it, you should see the default "Depot" page.
|
|
|
|
#### Language files
|
|
We create two language files for the system and the component **Depot** at
|
|
the directory /admin/language/en-GB/ naming it
|
|
|
|
- com_depot.ini
|
|
- com_depot.sys.ini
|
|
|
|
---
|
|
|
|
### Creating and managing Joomla database (b2_database)
|
|
|
|
With the new git branch **b2_database** we continue our workflow.
|
|
|
|
Joomla usually manage its content with a database. In our component, we use
|
|
a MariaDB database. At the time of development of this component we have PHP8.2,
|
|
and we use Mariadb database with version from 11.1,
|
|
client 15.2 for Linux (x86_64) using readline 5.1
|
|
We support MySQL and MariaDB; not tested support for PostgreSQL.
|
|
|
|
In the manifest file \<component_name\>.xml, here the file **depot.xml**,
|
|
there are installation instructions to "install", "uninstall", and
|
|
"update" the Joomla extension/component.
|
|
|
|
The SQL plain text files are stored in and as:
|
|
|
|
- admin/sql/
|
|
- install.mysql.utf8.sql
|
|
- uninstall.mysql.utf8.sql
|
|
|
|
- admin/sql/updates/mysql/
|
|
- 0.0.1.sql
|
|
- 0.0.4.sql
|
|
- 0.0.5.sql
|
|
|
|
#### Database table installation
|
|
1. When the component is installed for the first time, the file
|
|
**install.mysql.utf8.sql** is executed.
|
|
1. If the component is already installed, the update
|
|
scenario comes into play, the folder **admin/sql/updates/mysql/**: Only the files with higher version
|
|
numbers than the installed version of the component will be
|
|
executed in ascending order.<br>
|
|
Hint: The version of the installed component is stored in the
|
|
Joomla's table "#__schemas".
|
|
|
|
The "#__"-prefix is substituted automatically with the database prefix, (e.g. "jm_") which is defined in the configuration file (configuration.php) of the installed Joomla version as parameter $dbprefix.
|
|
|
|
**install.mysql.utf8.sql**
|
|
```sql
|
|
DROP TABLE IF EXISTS `#__depot`;
|
|
CREATE TABLE `#__depot`(
|
|
`id` SERIAL,
|
|
`component_name` VARCHAR(1024) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT NULL
|
|
COMMENT 'unique component name (ASCII characters only)',
|
|
`alias` VARCHAR(1024) NOT NULL DEFAULT '',
|
|
`description` VARCHAR(4000) NOT NULL DEFAULT '',
|
|
`quantity` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
|
`quantity_exp` INT(11) NOT NULL DEFAULT 0
|
|
COMMENT 'Exponent of the quantity (10^x of the number, usually 0 i.e. 10⁰)',
|
|
`asset_id` INT(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'FK to the #__assets table.',
|
|
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
`created_by` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
|
`checked_out` INT(11) NOT NULL DEFAULT 0,
|
|
`checked_out_time` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
`modified` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
`modified_by` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
|
`path` VARCHAR(400) NOT NULL DEFAULT '',
|
|
`state` TINYINT(4) NOT NULL DEFAULT 0
|
|
COMMENT 'Published=1,Unpublished=0,Archived=2,Trashed=-2',
|
|
`access` TINYINT(4) NOT NULL DEFAULT 0,
|
|
`params` VARCHAR(1024) NOT NULL DEFAULT '',
|
|
`image` VARCHAR(1024) NOT NULL DEFAULT '',
|
|
`ordering` INT(11) NOT NULL DEFAULT 0,
|
|
`version` int unsigned NOT NULL DEFAULT 1,
|
|
-- references to other tables:
|
|
`category_id` INT(11) NOT NULL DEFAULT 0,
|
|
`datasheet_id` INT(11) NOT NULL DEFAULT 0,
|
|
`datasheet_alt` VARCHAR(1024) NOT NULL DEFAULT '',
|
|
`manufacturer_id` INT(11) NOT NULL DEFAULT 0,
|
|
`stock_id` INT(11) NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
KEY `idx_state` (`state`),
|
|
KEY `idx_stock_id` (`stock_id`),
|
|
KEY `idx_manufacturer` (`manufacturer_id`),
|
|
UNIQUE KEY `aliasindex` (`alias`,`manufacturer_id`,`stock_id`)
|
|
) ENGINE=InnoDB
|
|
AUTO_INCREMENT=0
|
|
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
INSERT INTO `#__depot` (`component_name`,`alias`,`description`,`quantity`,`created`,
|
|
`ordering`,`state`,`manufacturer_id`) VALUES
|
|
('1N5404','1n5404','diode, rectifier 3A',9,'2023-09-25 15:00:00',1,1,1),
|
|
('1N4148','1n4148','diode, general purpose',1234,'2023-09-25 15:15:15',2,1,2);
|
|
```
|
|
The table is created in the database when the component is installed.
|
|
Also two lines of sample data are inserted into the table "#__depot".
|
|
|
|
#### Database table uninstallation
|
|
When the component is uninstalled the
|
|
**uninstall.mysql.utf8 sql** is executed.
|
|
We drop the used tables from the database.
|
|
|
|
**install.mysql.utf8.sql**
|
|
```sql
|
|
DROP TABLE IF EXISTS `#__depot`;
|
|
```
|
|
#### Database table update
|
|
When the component is updated the
|
|
**admin/sql/updates/mysql** folder with its files is executed.
|
|
|
|
Even if you do not need a database update, you can add an empty file in admin/sql/updates/mysql/0.0.2.sql to initialize the schema version.
|
|
|
|
In future versions, if you plan to use database tables, the update can be performed automatically.
|
|
We create an empty file, just with a comment "-- version 0.0.2"
|
|
**admin/sql/updates/mysql/0.0.2.sql**
|
|
|
|
```sql
|
|
-- version 0.0.2
|
|
```
|
|
|
|
#### Manifest file for extensions
|
|
The sql files are only executed if they exist in the \<component_name\>.xml manifest file. We add this after the namespace tag, just before the files information tag:
|
|
```php
|
|
<install> <!-- Runs on install -->
|
|
<sql>
|
|
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
|
|
</sql>
|
|
</install>
|
|
<uninstall> <!-- Runs on uninstall -->
|
|
<sql>
|
|
<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
|
|
</sql>
|
|
</uninstall>
|
|
<update>
|
|
<schemas>
|
|
<schemapath type="mysql">sql/updates/mysql</schemapath>
|
|
</schemas>
|
|
</update>
|
|
```
|
|
The **\<version\> tag** of the manifest must be updated to 0.0.2 and
|
|
also add the sql folder in the administration files section.
|
|
|
|
#### Table class
|
|
**src/table/DepotTable.php**
|
|
|
|
For each database table, you have to define a table class. The model
|
|
asks the table to get information or perform database operations.
|
|
|
|
This table class has to be defined in admin/src/Table/DepotTable.php file.
|
|
|
|
```php
|
|
<?php
|
|
namespace KW4NZ\Component\Depot\Administrator\Table;
|
|
|
|
use Joomla\CMS\Table\Table;
|
|
use Joomla\Database\DatabaseDriver;
|
|
|
|
\defined('_JEXEC') or die;
|
|
|
|
class DepotTable extends Table
|
|
{
|
|
function __contruct(DatabaseDriver $db)
|
|
{
|
|
parent::__contruct('#__depot', 'id', $db);
|
|
}
|
|
}
|
|
```
|
|
Joomla uses the **Table Object** to get item or record, insert records,
|
|
update or delete records for the database operations.
|
|
|
|
Methods in the table objects are:
|
|
|
|
1. **load()** to load the existing record from the database, passing
|
|
the primary key of the record.
|
|
1. **bind()** to set the new values for the fields.
|
|
1. **check()** to perform any validation.
|
|
1. **store()** to save the new values to the database.
|
|
1. **delete()** to delete the record from the database.
|
|
|
|
---
|
|
|
|
### Get a Form in Joomla component
|
|
|
|
The **Form** class of Joomla is used to create complex forms with flexible
|
|
layouts and dynamic properties. First, the form fields are defined in the
|
|
XML file. Then the view file gets the form from the model and layout file
|
|
displays the form.
|
|
|
|
#### XML Form file
|
|
**admin/forms/part.xml**
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<form>
|
|
<field
|
|
name="title"
|
|
type="text"
|
|
label="JGLOBAL_TITLE"
|
|
required="true"
|
|
/>
|
|
</form>
|
|
```
|
|
Similarly you can add other fields to the XML file.
|
|
|
|
#### View file
|
|
**admin/src/View/Part/HtmlView.php**
|
|
|
|
This file is similar to the view file added earlier for the "Parts" view.
|
|
The view file gets the form from the model in the display() method.
|
|
```php
|
|
<?php
|
|
namespace KW4NZ\Component\Depot\Administrator\View\Part;
|
|
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
|
|
|
\defined('_JEDEC') or die;
|
|
|
|
class HtmlView extends BaseHtmlView
|
|
{
|
|
protected $form;
|
|
protected $item;
|
|
|
|
public function display($tpl = null)
|
|
{
|
|
$this->form = $this->get('Form');
|
|
$this->item = $this->get('Item');
|
|
|
|
parent::display($tpl);
|
|
}
|
|
}
|
|
```
|
|
The code will look for the method **getForm()**
|
|
and **getItem()** in the model file.
|
|
We need to get the item to get the ID
|
|
of the record in case of editing the existing record.
|
|
|
|
#### Model file
|
|
**admin/src/Model/PartModel.php**
|
|
|
|
We need to extend the model class with the **AdminModel**.
|
|
The AdminModel class extends FormModel class. The **getForm()**
|
|
method gets the Form object for the edit form.
|
|
|
|
```php
|
|
namespace KW4NZ\Component\Depot\Administrator\Model;
|
|
use Joomla\CMS\MVC\Model\AdminModel;
|
|
|
|
\defined('_JEXEC') or die;
|
|
|
|
class PartModel extends AdminModel
|
|
{
|
|
public function getForm($data = array(), $loadData = true)
|
|
{
|
|
$form = $this->loadForm('com_depot.part',
|
|
'part', array('control' => 'jform',
|
|
'load_data' => $loadData));
|
|
|
|
if (empty($form)) {
|
|
return false;
|
|
}
|
|
|
|
return $form;
|
|
}
|
|
}
|
|
```
|
|
The **loadForm()** and **preprocessForm()** methods are defined in
|
|
the FromModel class and the **bind()** method is defined in the
|
|
Form class. The first argument (name) of loadForm() is set to
|
|
"com_depot.part". The second argument (form xml source) is "part",
|
|
and the third argument is the associative array for options.
|
|
|
|
The form is defined in the source file: **forms/part.xml**
|
|
|
|
After you have set the $form variable with the Form object,
|
|
you check to see if you are loading data to the form.
|
|
If you want to pre-load data for the form, you include an element
|
|
called "load_data" that is set to a boolean true.
|
|
Then, the method calls the loadFormData() method to get the data
|
|
for the form. This method gets any previously loaded data from
|
|
the session or database.
|
|
|
|
###### Modifying Form dynamically
|
|
|
|
Inside the getForm() method, before returning the $form, you can modify the form with many methods of the Form class. You can easily fine-tune your forms dynamically before they are rendered.
|
|
|
|
#### Layout file - rendering Form
|
|
**tmpl/part/edit.php**
|
|
|
|
After you get the form in the view file ($this->form), the form
|
|
is rendered in the layout file (edit.php).
|
|
|
|
```php
|
|
<?php
|
|
use Joomla\CMS\HTML\HTMLHelper;
|
|
|
|
$wa = $this->document->getWebAssetManager();
|
|
|
|
$wa->useScript('keepalive');
|
|
$wa->useScript('form.validate');
|
|
?>
|
|
<form action="<?= Route::_('index.php?option=com_depot&layout=edit&id=' .
|
|
(int) $this->item->id); ?>"
|
|
method="post" name="adminForm" id="item-form" class="form-validate">
|
|
|
|
<?= $this->form->renderField('title'); ?>
|
|
|
|
<input type="hidden" name="task" value="part.edit" />
|
|
<?= HTMLHelper::_('form.token'); ?>
|
|
</form>
|
|
```
|
|
The form validate script is required to submit the for. The renderField() method
|
|
of the Form class displays the field - both label and input.
|
|
|
|
We can access the form using following URL:
|
|
```php
|
|
administrator/index.php?option=com_depot&view=part&layout=edit
|
|
```
|
|
It displays edit.php layout file of the Part View. When the form is submitted, the
|
|
data is sent to the controller depending upon the action buttons in the toolbar.
|
|
|
|
Please remember to add the additional folder `form` to the Manifest file "depot.xml", i.e.
|
|
just a line before `<folder>services</folder>` :
|
|
```xml
|
|
<folder>form</folder>
|
|
```
|
|
|
|
---
|