Forums | Mahara Community
Copy "tagged journal entry" bloc
17 November 2015, 11:56 AM
Dear community's members,
I am in the process to build a collection that we be copied by a lot of users.
The concept I would like to be able to implement is this one :
- Let's say that in each of the originals pages of the collection, I have a "tagged journal entry" bloc.
Is there a configuration possible so that the user that will copy this collection we be able to obtain pages in which there is already a "tagged journal entry" bloc?
At the moment, the result of the copy shows an empty column where I would like to find a "tagged journal entry".
The really best would be to obtain a "tagged journal entry" bloc, even empty of articles. I would like the bloc to be simply there, "waiting" for the articles to be written and tagged.
18 November 2015, 12:21 PM
Unfortunately, that's a known shortcoming in the "tagged posts" block. See: https://bugs.launchpad.net/mahara/+bug/1027739
So currently the block is set to not be copyable at all. You might be able to work around this with some light hacking. In htdocs/artefact/blog/blocktype/taggedposts/lib.php, there is a method called "public static function default_copy_type()", which controls how Mahara tries to copy the block. For the taggedposts block, because we were unable to implement copying, we set this to return "nocopy", which tells Mahara not to copy the block at all.
If you instead changed it to return "shallow", then it should instead create an empty tagged journal entries block in copies of the page.
02 December 2015, 8:19 AM
We had started looking into implementing copying of the tagged journal entries block, but it got out of hand quite quickly because the question then is where the journal entries that are copied are put esp. when a page is copied twice. Since the entries can be pulled together from multiple source journals, would we set those up or just one journal or ...
If you have any thoughts on that, please let us know.
07 December 2015, 9:39 AM
I read your post - warm thanks for your interest.
You are right and I join you: it could not a good approach to copy the contents of the « tagged journal entry » block.
In fact, the proposition made by Aaron to use the "shallow" mode is closer to my needs.
Before Aaron initiate me about this "shallow" mode, I wasn't aware about it.
As I replied him, however, my situation would be totally resolved if this shallow mode was just a little "deeper" that his actual behavior.
So, to suit my needs, the really best functionnality to add to the "shallow" mode assigned to the tagged journal entry block, would be to keep the tag from the configuration of the original block.
Do you feel that this could be possible?
07 December 2015, 9:10 AM
I tried your suggestion, which was to change, in the file htdocs/artefact/blog/blocktype/taggedposts/lib.php, the return value of the method public static function default_copy_type(), from the default value nocopy to the value shallow.
You were right : this is a concrete and real improvment toward my needs. I really appreciate.
With that config, the pages copied in the flow of a collection copy contain an unconfigured bloc « tagged journal entry ».
My users will then be freed to manually insert those blocks in those pages.
Still, they will have to configure the block and choose a tag value for the block.
While involve in this improvment process, I wonder if it is possible to keep the original block configuration; I mean keep the original tag while using this shallow mode? (Or maybe another mode?)
In facts, when a user copy this collection containing pages with tagged journal entry block, he already have, in his portfolio, at least one draft acticle containing the necessary tags; the point I want to highlight here is that those tags are already existing in a journal in his own portfolio.
07 December 2015, 11:46 AM
There is a block default copy option called "reference" which just copies the contents of block_instance.configdata. But unfortunately that won't work for the artefact/blog/blocktype/taggedposts blocktype, because it stores the list of tags in a separate table (blocktype_taggedposts_tags).
So it would require some extra work to get that to work properly. Probably implementing a "rewrite_blockinstance_extra_config" method for the blocktype. I think it might not be too hard, if you know any PHP. Take a look at the copy() method in htdocs/blocktype/lib.php to see how rewrite_blockinstance_extra_config gets called.
16 December 2015, 10:34 AM
It might be not too hard, if I knew PHP... Which is not the case, and I am sorry about that. But I know some people around that could help.
If it's possible, I would like to confirm my understanding of the case before I ask around for some support.
As you suggested, I took a look in the code, and looked into the database to understand the behavior.
- Let's say that the prerequisite is to visit the htdocs/artefact/blog/blocktype/taggedposts/lib.php file, in which we set the return value of the method public static function default_copy_type() to shallow. (Alternatively, we could set this return value to reference, but it that case, it worths nothing more, and so we fix it to shallow.)
- Now, let's say that we are in the process of copying a page which contains a tagged journal entry block.
- The goal is to first get the original "tag" value of the source "tagged journal entry" block, which is store in blocktype_taggedposts_tags table, and then to insert a new row into blocktype_taggedposts_tags for the new block_instance along with this source tag value.
- While acting in the blocktype_taggedposts_tags table to add this new row, there is nothing to alter or to rewrite in the block_instance table, which will be already well-formed.
To achieve this, in a precedent post, you suggested to implement a rewrite_blockinstance_extra_config method for the taggedposts blocktype.
This method is called before the new block is saved into the database, so you will not know the new block's ID yet, and consequently this method should not insert records directly into the database
So, I guess that we'll have to use the alternate method suggested on the same wiki section, which is to :
Update the new block's
BlockInstance object (which is passed by reference) in such a way that your plugin will recognize the added data and save it to the proper tables when its commit() method is called
Is this right? Thank you for your lights!
16 December 2015, 4:36 PM
Hm... on further inspection I think my updated advice in the wiki may have been incorrect. :( The problem is that the commit() method in question belongs to the BlockInstance class, not to the PluginBlocktype subclass. BlockInstance is a sort of helper class which is not subtyped for different blocktype plugins. They all use the same BlockInstance implementation. Differences in behavior between different blocktypes are handled by BlockInstance calling various "hook" functions of the PluginType class.
And unfortunately, that BlockInstance->commit() method does not contain any hook methods for you to customize its behavior with. All it does is insert into columns of the "block_instance" database table, and serialize the block's configdata and insert that into block_instance.configdata...
So I guess there would be actually these two ways to do it:
1. Use an event handler. BlockInstance->commit() fires a "blockinstancecommit" event at the end, passing the BlockInstance object. There is some documentation about the event handler system here, which I believe is up to date. ;) https://wiki.mahara.org/wiki/Developer_Area/Events_API . The event gets passed the full BlockInstance object, so you'd still need to add the list of tags to the BlockInstance object in rewrite_blockinstance_extra_config. (This could be as simple as "$block->tags = ..."). Unfortunately, this event fires after every time a block is created or modified, not just after a copy. So your event handler would have to be able to handle that.
2. Or Make a change to Mahara core, to give PluginBlocktype subclasses a hook method for making changes to a copied block instance after its record in the block_instance table has been created and the primary key is known. (I'm actually kind of surprised we don't have this already.) This hook method would probably best be invoked at the end of the BlockInstance->copy() method, after it does $newblock->commit().
Since you're patching Mahara core anyway, you may as well go with option #2, since it would be a bit cleaner and easier.
19 December 2015, 10:50 AM
My php-competent friend worked with me on the subject of the method number 2.
I made tests, under all the available modes (nocopy, reference, shallow, full) and the behavior seems adequate.
I wonder if we can submit you our new code extract so that you can validate that it is un sync with what you could have expect? Is this forum could be a good place to post it?
Thank you for your patience,
23 December 2015, 12:25 PM
Great that you could get something to work! If you'd like to contribute your changes to the Mahara core project, you could put your patch through our code review (see https://wiki.mahara.org/wiki/Developer_Area/Contributing_Code for more information) or post patch as a file attachment on the existing wishlist item in Launchpad. We can then review it and provide you feedback on it.
If you do not want to share your code with the rest of the community, we can review the functionality for you on a consulting basis.