With Joomla 3.1.4, how do we programmatically insert tags?

1,140 views
Skip to first unread message

Jindan Zhou

unread,
Jul 26, 2013, 1:08:57 AM7/26/13
to joomla-de...@googlegroups.com
I have noticed that prior to 3.1.4 (I've used 3.1.1), you would instance $JTable, then you supply a list of tag id to the metadata field of your data, Joomla then takes care of tag map, for example:
 {"tags":[2],"robots":"","author":"","rights":"","xreference":""}

However the same does not work for 3.1.4 anymore, the key `tags` is gone in metadata field of #_content. How do we add tags to article now?

Thanks,

Sample code worked for 3.1.1:

$table = JTable::getInstance('Content', 'JTable', array());
$data = array(
'title' => $your_title_string,
...
        'metadata' => array(
                 'tags' => $list_of['tags'],
                  ....
);
    $table->bind($data);
    $table->check();
    $table->store();  

Jindan Zhou

unread,
Jul 26, 2013, 10:52:59 PM7/26/13
to joomla-de...@googlegroups.com
Another observation with 3.1.4 the method in my previous post does not update #_ucm_base and #ucm_content anymore, while in 3.1.1 it does. So anyone has a method to programmatically batch insert articles?

Thanks,

Amy Stephen

unread,
Jul 27, 2013, 12:36:37 PM7/27/13
to joomla-de...@googlegroups.com
Seriously? If so, that's a bug.


--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.
To post to this group, send an email to joomla-de...@googlegroups.com.
Visit this group at http://groups.google.com/group/joomla-dev-general.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Bakual

unread,
Jul 27, 2013, 1:00:47 PM7/27/13
to joomla-de...@googlegroups.com
There is indeed a bug which broke tag saving for 3rd party extensions. The storage was changed to use an observer but I can't get it to fire fof my extension, and the old way using metadata, preStorage and postStorage doesn't work anymore.

I'm still trying to figure out how this observer stuff works.

Amy Stephen

unread,
Jul 27, 2013, 1:39:44 PM7/27/13
to joomla-de...@googlegroups.com
Quick glance at patch - would you have to register an observer?

https://github.com/joomla/joomla-cms/commit/f747e97f1709eccfdb634088499b65c7c7dd00a3#L6R61



On Sat, Jul 27, 2013 at 12:00 PM, Bakual <werbe...@bakual.ch> wrote:
There is indeed a bug which broke tag saving for 3rd party extensions. The storage was changed to use an observer but I can't get it to fire fof my extension, and the old way using metadata, preStorage and postStorage doesn't work anymore.

I'm still trying to figure out how this observer stuff works.

Amy Stephen

unread,
Jul 27, 2013, 1:59:35 PM7/27/13
to joomla-de...@googlegroups.com
@Bakual - looks like Michael has run into this - he left a message https://github.com/joomla/joomla-cms/pull/1561#issuecomment-21669572 on a github issue, sharing a link to his extension commit to deal with the problem

Bakual

unread,
Jul 27, 2013, 2:10:55 PM7/27/13
to joomla-de...@googlegroups.com
Yeah, apparently this is what's missing when I want to use the new way. The old way is still broken.
 
It's a bit unfortunate that this is hidden in a cms.php. Imho it should be in the com_weblinks or com_contact so extension developer will find this reference when they look how it works.

Am Samstag, 27. Juli 2013 19:39:44 UTC+2 schrieb Amy Stephen:
Quick glance at patch - would you have to register an observer?

https://github.com/joomla/joomla-cms/commit/f747e97f1709eccfdb634088499b65c7c7dd00a3#L6R61

On Sat, Jul 27, 2013 at 12:00 PM, Bakual <werbe...@bakual.ch> wrote:
There is indeed a bug which broke tag saving for 3rd party extensions. The storage was changed to use an observer but I can't get it to fire fof my extension, and the old way using metadata, preStorage and postStorage doesn't work anymore.

I'm still trying to figure out how this observer stuff works.

--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-general+unsub...@googlegroups.com.

Amy Stephen

unread,
Jul 27, 2013, 2:52:54 PM7/27/13
to joomla-de...@googlegroups.com
Wait - are you saying that you do need to register an observer? Or that Micheal's fix was what you needed. /me is so easily confused, sorry!


To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Bakual

unread,
Jul 27, 2013, 3:14:00 PM7/27/13
to joomla-de...@googlegroups.com
  • If you want to use the new way, you need to register the observer (works in the table constructor). This will however only work on Joomla 3.1.4 and higher, but is by far the better code (imho *g*)
  • If you want to use the old way, you need the fix Michael described. This is the only way tags in your extension will work from Joomla 3.1.0 up to the current one (and hopefully also in J3.5 - who knows).
So if your extension supports tags, you need to change something anyway. And that's a bad thing called backward compatibility break.

Am Samstag, 27. Juli 2013 20:52:54 UTC+2 schrieb Amy Stephen:
Wait - are you saying that you do need to register an observer? Or that Micheal's fix was what you needed. /me is so easily confused, sorry!
On Sat, Jul 27, 2013 at 1:10 PM, Bakual <werbe...@bakual.ch> wrote:
Yeah, apparently this is what's missing when I want to use the new way. The old way is still broken.
 
It's a bit unfortunate that this is hidden in a cms.php. Imho it should be in the com_weblinks or com_contact so extension developer will find this reference when they look how it works.

Am Samstag, 27. Juli 2013 19:39:44 UTC+2 schrieb Amy Stephen:
Quick glance at patch - would you have to register an observer?

https://github.com/joomla/joomla-cms/commit/f747e97f1709eccfdb634088499b65c7c7dd00a3#L6R61

On Sat, Jul 27, 2013 at 12:00 PM, Bakual <werbe...@bakual.ch> wrote:
There is indeed a bug which broke tag saving for 3rd party extensions. The storage was changed to use an observer but I can't get it to fire fof my extension, and the old way using metadata, preStorage and postStorage doesn't work anymore.

I'm still trying to figure out how this observer stuff works.

--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-general+unsubscribe@googlegroups.com.
To post to this group, send an email to joomla-de...@googlegroups.com.

Amy Stephen

unread,
Jul 27, 2013, 3:22:34 PM7/27/13
to joomla-de...@googlegroups.com
Well, that's what it looked like to me, too, but Micheal's comment seemed to state otherwise.

OK. Thanks.

And yes, those statements belong in the individual component so it's clear what an extension should do. Full agreement.


To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Bakual

unread,
Jul 27, 2013, 3:27:40 PM7/27/13
to joomla-de...@googlegroups.com
I think what Michael meant is that it's not the fault of this particular PR that introduced the observer stuff. The break was before that PR when there was somehow a change related to storing the tags in the metadata field.

Michael Babker

unread,
Jul 27, 2013, 3:35:55 PM7/27/13
to joomla-de...@googlegroups.com
Exactly.  At the time Beat had this patch coded and submitted, we already had the break of the storage field committed for some time.  When I was testing his patch, the only change I had to make to my code (which I honestly hadn't tested since 3.1.1's release) was the storage field.  With Beat's patch, that was the only change.  Without it, well, I don't even want to know...


To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Fernando Cassia

unread,
Jul 27, 2013, 5:48:20 PM7/27/13
to joomla-de...@googlegroups.com
On Fri, Jul 26, 2013 at 2:08 AM, Jindan Zhou <jin...@gmail.com> wrote:
> I have noticed that prior to 3.1.4 (I've used 3.1.1), you would instance
> $JTable, then you supply a list of tag id to the metadata field of your
> data, Joomla then takes care of tag map, for example:
> {"tags":[2],"robots":"","author":"","rights":"","xreference":""}

Could we please stop using the word "programmatically"? It sounds
wrong, it feels wrong (to me it sounds at least redundant), and it's
as stupid as a team of surgeons saying "how to perform a coronary
by-pass medically?" or a group of musicians asking "how to play
Beethoven musically?"

If we're talking about software we already are speaking about doing
things with programs. You could ask "is there an API to do XYZ?" Or
"how to do xyz from my code?"

As you can see here Im not the only one rubbed the wrong way about
bothb"programatically" and the one that does exist, "programatically",
but which is more slanted toward following a "programme"

http://english.stackexchange.com/questions/12245/frequent-use-of-word-not-found-in-dictionary-programatically

Ironically, its been MSFT Technet one of the bigest offenders in this
regard... along with programmer forums in India and China, as far as
I've seen...
FC
>
> However the same does not work for 3.1.4 anymore, the key `tags` is gone in
> metadata field of #_content. How do we add tags to article now?
>
> Thanks,
>
> Sample code worked for 3.1.1:
>
> $table = JTable::getInstance('Content', 'JTable', array());
> $data = array(
> 'title' => $your_title_string,
> ...
> 'metadata' => array(
> 'tags' => $list_of['tags'],
> ....
> );
> $table->bind($data);
> $table->check();
> $table->store();
>
> --
> You received this message because you are subscribed to the Google Groups
> "Joomla! General Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to joomla-dev-gene...@googlegroups.com.
> To post to this group, send an email to joomla-de...@googlegroups.com.
> Visit this group at http://groups.google.com/group/joomla-dev-general.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
During times of Universal Deceit, telling the truth becomes a revolutionary act
Durante épocas de Engaño Universal, decir la verdad se convierte en un
Acto Revolucionario
- George Orwell

Amy Stephen

unread,
Jul 27, 2013, 6:01:23 PM7/27/13
to joomla-de...@googlegroups.com
Fernando - I believe the distinction was between manually entering tags, as a user, and how to use the API. As you can see from our responses, it was clear to us.

Since the API has indeed changed, and since extensions using tags will have been broken by this release, it would be best if this topic stayed focused so that people do not have to read through superfluous comment.

/me shaking her head

Fernando Cassia

unread,
Jul 27, 2013, 6:55:33 PM7/27/13
to joomla-de...@googlegroups.com
On Sat, Jul 27, 2013 at 7:01 PM, Amy Stephen <amyst...@gmail.com> wrote:
> /me shaking her head

Sorry about that.
FC

Amy Stephen

unread,
Jul 27, 2013, 9:53:58 PM7/27/13
to joomla-de...@googlegroups.com
It's okay. =)


FC

Bakual

unread,
Jul 28, 2013, 2:34:21 PM7/28/13
to joomla-de...@googlegroups.com
I did a PR to include this fix into the legacy form model. This way extensions using Tags will only be broken in Joomla 3.1.4 (assuming it goes into Joomla 3.1.5)
I've changed the code a bit so it should not interfere with extensions using the new way.
 
Tracker:
PR:
 
Please test :-)

Amy Stephen

unread,
Jul 28, 2013, 2:47:09 PM7/28/13
to joomla-de...@googlegroups.com
+1

So, is the old way deprecated?


To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Bakual

unread,
Jul 28, 2013, 3:15:50 PM7/28/13
to joomla-de...@googlegroups.com
So, is the old way deprecated?
 
I have no clue

Jindan Zhou

unread,
Jul 29, 2013, 12:53:03 AM7/29/13
to joomla-de...@googlegroups.com
It didn't work for me;-) My original $row['tags'] is an array of integers corresponding to existing tag ids in #_tags, I've tried to assign this array to $data['tags'] and remove it from the $data['metadata'], still I wasn't able to tag the article: the two #_ucm* tables are not updated.

Bakual

unread,
Jul 29, 2013, 2:53:28 AM7/29/13
to joomla-de...@googlegroups.com
This PR only fixes the storing for extensions using their own tags. It doesn't solve anything if you want to tag articles from com_content.

I didn't try that but it should work if the tags array is added to the $data directly. Assuming you want to do that from within the CMS. Since currently the observer is loaded in cms.php instead of the table, it may fail if you try to do that from outside of the CMS?

Bakual

unread,
Jul 29, 2013, 9:00:42 AM7/29/13
to joomla-de...@googlegroups.com
It's a bit unfortunate that this is hidden in a cms.php. Imho it should be in the com_weblinks or com_contact so extension developer will find this reference when they look how it works.

I did a PR to move the calls to the respective tables as they make more sense there and can be better found:

 
Message has been deleted

Jindan Zhou

unread,
Jul 29, 2013, 11:15:48 AM7/29/13
to joomla-de...@googlegroups.com
I call the following code from with in the administrator directory:

<?php
define( '_JEXEC', 1 );
define('JPATH_BASE', dirname(dirname(__FILE__)));
define( 'DS', DIRECTORY_SEPARATOR );

require_once (JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once (JPATH_BASE . DS . 'includes' . DS . 'framework.php');
require_once (JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'factory.php' );

define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_BASE . DS . 'administrator' . DS . 'components' . DS . 'com_content');
$mainframe = JFactory::getApplication('administrator');

require_once (JPATH_ADMINISTRATOR.'/components/com_content/models/article.php');


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

$data = array(
    'title' => 'my title',
    'alias' => time(),
    'introtext' => 'my introtext',
    'state' => 1,
    'catid' => 8,
);

$data['tags'] = $tags;
/* var_dump($data['tags']); */


$table->bind($data);
$table->check();
$table->store();

?>
where $tags is the array of the existing tag ids, the article would insert without problem, but not with the tags, do you see anything wrong in the code? Thanks,

Bakual

unread,
Jul 29, 2013, 11:54:56 AM7/29/13
to joomla-de...@googlegroups.com
I'd say it would work if you included the /libraries/cms.php file as well. Currently it's the place where the JTableObserverTags is mapped to the tables. Imho it's the wrong place and it should go into the respective table for various reasons, yours (using the table outside of the CMS scope) is one of them.
 
Can you test if this PR will fix your issue? https://github.com/joomla/joomla-cms/pull/1612

Amy Stephen

unread,
Jul 29, 2013, 11:58:52 AM7/29/13
to joomla-de...@googlegroups.com
What specific file have you included this in?


To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Amy Stephen

unread,
Jul 29, 2013, 12:10:53 PM7/29/13
to joomla-de...@googlegroups.com

Jindan Zhou

unread,
Jul 29, 2013, 12:50:46 PM7/29/13
to joomla-de...@googlegroups.com
I put var_dump($item->tags); after L295, not seeing anything;
put var_dump($data); before L442, not seeing anything.

Both case insert articles without problem.

The code is self contained - does not include external data file, just save it in adminitrator folder, and call `php script.php`

Jindan Zhou

unread,
Jul 29, 2013, 1:20:58 PM7/29/13
to joomla-de...@googlegroups.com
Was trying to apply your patch, while all files patched except for:
patching file libraries/legacy/table/content.php
Hunk #1 FAILED at 30.
1 out of 1 hunk FAILED -- saving rejects to file libraries/legacy/table/content.php.rej
but I manually edited the file, still a no go.

Also I have now  added the line `require_once (JPATH_BASE . DS . 'libraries' . DS . 'cms.php');` in my code, that didn't help neither.

What I am wondering now is: in my code I have defined `$tags = array(2, 3);` and assigned to $data array as: `$data['tags'] = $tags;` is this the format that com_tags would accept?
On another attempt I have blindly tried to 'jsonify' the tags array:

$registry = new JRegistry;
$registry->loadArray($tags);
$data['tags'] = (string) $registry;

That did not help neither;-)

Bakual

unread,
Jul 29, 2013, 3:36:31 PM7/29/13
to joomla-de...@googlegroups.com
Hmm, can't get it to work with your code as well.
Something seems to be missing but I can't find it neither.
 
The tags data looks correct to me.
I saw that the article model does add the tags to $table->newTags in some case. But other than that I found nothing special.
 
Maybe someone who wrote the actual code could help here...
 

Am Montag, 29. Juli 2013 17:15:48 UTC+2 schrieb Jindan Zhou:

Jindan Zhou

unread,
Jul 29, 2013, 4:04:22 PM7/29/13
to joomla-de...@googlegroups.com
Well, the problem is partially solved by instantiate ContentModelArticle rather than JTable, using the same $data:

 $new_article = new ContentModelArticle();
// same data;
$new_article->save($data);

Both article and tags are inserted successfully. Except, as I reported a while back, this method takes *substantially* longer time and cpu.
getInstance JTable: insert about 40k articles in less than 4 hours;
ContentModelArticle: insert the same about of articles about 40 hours.

See my post earlier:
https://groups.google.com/forum/#!searchin/joomla-dev-general/contentmodelarticle/joomla-dev-general/KOeziHUVifw/teEBmyy15SgJ

Jindan Zhou

unread,
Jul 30, 2013, 6:32:01 PM7/30/13
to joomla-de...@googlegroups.com
Finally get the problem fixed.
With getInstance JTable, the new com_tags component won't take tags array if it is bound to $data, instead you need to bind it to the $table object: $table->newTags = $data['tags']; before $table->bind($data); the newly inserted articles are now properly tagged.

With ContentModelArticle, you can still bind it to $data.

My new question: what if I want to supply an array of tag titles rather than int tag ids?


On Friday, July 26, 2013 12:08:57 AM UTC-5, Jindan Zhou wrote:
I have noticed that prior to 3.1.4 (I've used 3.1.1), you would instance $JTable, then you supply a list of tag id to the metadata field of your data, Joomla then takes care of tag map, for example:
 {"tags":[2],"robots":"","author":"","rights":"","xreference":""}

However the same does not work for 3.1.4 anymore, the key `tags` is gone in metadata field of #_content. How do we add tags to article now?

Thanks,

Sample code worked for 3.1.1:

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

'title' => $your_title_string,
...
        'metadata' => array(
                 'tags' => $list_of['tags'],
                  ....
);

Matt Thomas

unread,
Jul 30, 2013, 9:13:00 PM7/30/13
to Joomla! General Development
Thanks for posting back with a solution. I was looking at this prior to 3.1.4. and found it fairly confusing. I'll try your solution for my use case as soon as I can.

Since tags have an alias attribute, more than one tag can have have the same title. It seems like that then forces you to do a lookup on the title to guess the ID. To me, it seems logical to enforce unique titles (like K2), and even eliminate the alias attribute, so that you can supply an array of titles, and even create new tags on the fly.

Good thread.


Best,

Matt Thomas
Founder betweenbrain
Phone: 203.632.9322
Twitter: @betweenbrain



--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to joomla-dev-gene...@googlegroups.com.

Bakual

unread,
Jul 31, 2013, 12:57:07 AM7/31/13
to joomla-de...@googlegroups.com
I think new tags are created when the tag title is passed with a hash, like #yourTag.
But I would have to look that up closer to be sure ;)

Bakual

unread,
Jul 31, 2013, 5:24:28 AM7/31/13
to joomla-de...@googlegroups.com
I was almost correct. They're passed from the form as #new#yourTag

Bakual

unread,
Jul 31, 2013, 6:10:35 AM7/31/13
to joomla-de...@googlegroups.com
What I now basically do in my component to migrate the tags from my old own tagging system. This works fine for me. Maybe it helps.

// $items = array of items to migrate

$table = new SermonspeakerTableSermon($db);
foreach ($items as $item)
{
$table->load($item->id);
$table->newTags = array(#new#Tag1, #new#Tag2);
$table->store();
}

The tags will automatically be created if not already present.

Jindan Zhou

unread,
Jul 31, 2013, 6:18:12 PM7/31/13
to joomla-de...@googlegroups.com
ah, yes, I remember when I was browsing the code I actually see lines mentioning #new#, too bad didn't pay attention then;-)

AJH

unread,
Sep 17, 2013, 12:03:48 AM9/17/13
to joomla-de...@googlegroups.com
What a pain Tags have been.  The API has changed at least three times since I added it to my component.
Reply all
Reply to author
Forward
0 new messages