Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct pattern to write to joomla assets table?

Tags:

php

joomla

I'm currently modifying a component to include ACL support. I would like to create the correct #_assets row for every category/item created. What would the correct procedure be to respect hierarchy and recompute lft and rght values?

Example:
Component

  • Category (lft:0 rght:1)
    • Item (lft:2 rght:3)
  • Category (lft:4 rght:5)
    • Item (lft:6 rght:7)
    • New Item (lft:? rght:?)
  • Category (lft:8 rght:9)
like image 755
G3z Avatar asked Jan 25 '26 15:01

G3z


2 Answers

Generally you don't write directly to #_assets normally you would add ACL support as shown in the tutorial and then as each item is saved the acl is updated.

You probably want to read this article as well on adding ACL rules to your component as well.

Finally if you're talking about processing existing records to add ACL then the most common approach is to process each record using your updated model (that now has ACL support) to re-save them. This will result in the ACL being applied properly not just updating the #_assets table.

like image 178
Craig Avatar answered Jan 28 '26 04:01

Craig


if you want to add your component's item to the assets table:

I'll assume you have added the file access.xml w/ the sections component, categories, and item like so:

....

**<section name="item">
    <action name="core.delete" title="JACTION_DELETE" description="COM_CONTENT_ACCESS_DELETE_DESC" />
    <action name="core.edit" title="JACTION_EDIT" description="COM_CONTENT_ACCESS_EDIT_DESC" />
    <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_CONTENT_ACCESS_EDITSTATE_DESC" />
</section>**

....

Here I will refer to the section item as the component's item (i.e. an article, a banner, a weblink, etc.)

Your component item table must have the column asset_id, because the existence of this field triggers the saving of this item to the #__assets table

Jtable class

 ... __construct()
{
...
        if (property_exists($this, 'asset_id'))
        {
            $this->_trackAssets = true;
        }
...
}

If you are following joomla's component development and file structure guidelines, then your ComponentTableItem store() method would call parent::store(); It is in the parent class, JTable->store(), that the insert to the the assets table occurs. If the item record was successfully saved to its table, then the class continues by checking for the existence of the asset_id field.

JTable->store() checks

    // If the table is not set to track assets return true.
    if (!$this->_trackAssets)
    {
        return true;
    }

If this exists, then code continues to execute getting the asset Parent id, the asset name to use when adding the record to the table, and the title of this item.

Take a look at JOOMLA_ROOT/libraries/joomla/database/table.php and search for method store(), code excerpt:

$parentId = $this->_getAssetParentId();
$name = $this->_getAssetName();
$title = $this->_getAssetTitle();

If you want to control how the asset name gets recorded, for example, com_yourComponent.item.12 or com_yourComponent.event.14, or com_yourComponent.YOURITEM.ID, (look at your joomla database, table #__assets to better understand what I am referring to, i.e. the structure of the assets' names) you can, or might need to, rewrite the methods _getAssetParentID(), _getAssetName(), and _getAssetTitle() in your Component's table class.

Assuming a new item, once recorded to the #__assets table, the method UPDATES the recently added item record with the corresponding asset id, i.e. #assets.id = #_yourComponent_item.asset_id. From JTable->store() continued:

    if (empty($this->asset_id))
    {
        // Update the asset_id field in this table.
        $this->asset_id = (int) $asset->id;

        $query = $this->_db->getQuery(true);
        $query->update($this->_db->quoteName($this->_tbl));
        $query->set('asset_id = ' . (int) $this->asset_id);
        $query->where($this->_db->quoteName($k) . ' = ' . (int) $this->$k);
        $this->_db->setQuery($query);

        if (!$this->_db->query())
        {
            $e = new JException(JText::sprintf('JLIB_DATABASE_ERROR_STORE_FAILED_UPDATE_ASSET_ID', $this->_db->getErrorMsg()));
            $this->setError($e);

            return false;
        }

    }

Of course, as cppl mentioned above, you must have implemented the ACL rules to your component's item form and binded these before saving.

I strongly suggest you read the documentation cppl redirects you to.

like image 32
IberoMedia Avatar answered Jan 28 '26 04:01

IberoMedia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!