0

I work on a custom Joomla 3 module that creates articles programmatically based on user input. I can create the articles, but I could not find a way to set the article options and associations when the article is created. I found this article on where the options are stored in the Joomla DB, but I would prefer not to write the DB directly, if possible. I would also need a solution to create associations for the newly created articles. For your reference, you can see my current source code below.

Thanks, W.

static function createArticle(GNGLocation $loc, GNGLang $lang, $title, $alias, $intro, $summary, $included, $excluded, $imageStr) {

$table = JTable::getInstance('Content', 'JTable', array());

$jcat = $loc->get('jcat_id_tour');
$jlang = $lang->get('joomlaName');

$intro .= "{loadposition gngscrollarticle}<BR>{loadposition gngpricingtable}<BR>{loadposition gngcontact}";

$data = array(
    'catid' => $jcat,
    'title' => $title,
    'alias' =>  $alias,
    'language' => $jlang,
    'introtext' => $summary,
    'fulltext' => $intro,
    'state' => 0,
);

// Bind data
if (!$table->bind($data))
{
    throw new Exception("Failed to bind article data. Error: " . $table->getError());
}

// Check the data.
if (!$table->check())
{
    throw new Exception("Failed to check article data. Error: " . $table->getError());
}

// Store the data.
if (!$table->store())
{
    throw new Exception("Failed to store article data. Error: " . $table->getError());
}


//write custom field values 

JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/models');

$model =& JModelLegacy::getInstance('Article', 'ContentModel', array('ignore_request'=>true));
$appParams = JFactory::getApplication()->getParams();
$model->setState('params', $appParams);
$item =& $model->getItem($table->id);


$custom_fields = FieldsHelper::getFields('com_content.article',  $item, True);
$custom_fields_by_name = \Joomla\Utilities\ArrayHelper::pivot($custom_fields, 'name');
$included_value = 'haliho';

$model_field = JModelLegacy::getInstance('Field', 'FieldsModel', ['ignore_request' => true]);
$model_field->setFieldValue($custom_fields_by_name['excluded']->id, $item->id, $excluded);
$model_field->setFieldValue($custom_fields_by_name['included']->id, $item->id, $included);

return $table->id;

}

1 Answer 1

1

The article options are held in json-encoded format in the attribs field in the database, so that is what you should set, eg:

$data["attribs"] = array("show_title" => 0, "show_tags" => 0);

The names of the options can be found from the edit article xml form definition in administrator/components/com_content/models/forms/article.xml.

The Content Table code in libraries/src/table/content.php has the lines:

if (isset($array['attribs']) && is_array($array['attribs']))
{
    $registry = new Registry($array['attribs']);
    $array['attribs'] = (string) $registry;
}

and this has the effect of converting your array of options into a json-encoded string, so you don't need to worry about it.

(As far as I can see, nowadays the standard way of defining which fields should be json-encoded is to use the Table class

protected $_jsonEncode = array();

variable, and you specify a list of the field names of fields which should be json-encoded. But maybe the hard-coded com_content code predates that and hasn't been changed.)

The creation of the associations is a bit more complex because the standard code for this isn't within the Table functionality but rather within the AdminModel class (found in libraries/src/MVC/Model/AdminModel.php), and it does direct writes to the associations database table. So my recommendation would be to study the relevant code within AdminModel::save() and copy it, adapting it to your needs if necessary.

Alternatively you can set up a model class which inherits from AdminModel, but you have to do a bit of fiddling with your code to make it work, and it's going to be more open to problems with Joomla upgrades I reckon, because you're not really using AdminModel in the standard way. However, if you want to go down that route you could use something like the code below. I've tested a version of the code and it works for me. It would fit after your $data = array(...) line, replacing the calls to Table functionality.

class MyModel extends JModelAdmin
{

    public function save($data)
    {
        $this->option = "com_content";  // needed to make it save to the content table
        $this->name = "0";              // needed to make the primary key = 0 (indicating a new record)
        $this->associationsContext = "com_content.item";    // needed for setting the associations
        parent::save($data);
    }

    public function getTable($type = 'Content', $prefix = 'JTable', $config = array())  // how AdminModel gets the com_content table
    {
        return JTable::getInstance($type, $prefix, $config);
    }

    public function getForm($data = array(), $loadData = true) {} // abstract function in parent, so needs to be present
}

$data["attribs"] = array("show_title" => 0, "show_tags" => 0);
$data["associations"] = array("en-NZ" => 47);   // replace with a relevant value
$data["id"] = 0;

$model = new MyModel();
$model->save($data);
3
  • Wow, thanks a lot for the exceptionally detailed answer! I will give it try and let you know, how it worked! Commented May 26, 2020 at 10:57
  • I tried what you wrote about the options part, it works perfectly thank you! The assosciation part sounds a bit more tricky, but will come back when I'm done with it. Thanks! Commented May 30, 2020 at 13:49
  • Based on your guidance, I could also implement the association part reusing the AdminModel::save() code. Thanks again! Commented Jun 12, 2020 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.