We use cookies to improve your experience. No personal information is gathered and we don't serve ads. Cookies Policy.

ExpressionEngine Logo ExpressionEngine
Features Pricing Support Find A Developer
Partners Upgrades
Blog Add-Ons Learn
Docs Forums University
Log In or Sign Up
Log In Sign Up
ExpressionEngine Logo
Features Pro new Support Find A Developer
Partners Upgrades
Blog Add-Ons Learn
Docs Forums University Blog
  • Home
  • Forums

Hooks?

Developer Preview

Mark Croxton's avatar
Mark Croxton
319 posts
10 years ago
Mark Croxton's avatar Mark Croxton

Just checking that hooks for events in the control panel - e.g. ‘entry_submission_end’ - will be in the final release?

       
Low's avatar
Low
407 posts
10 years ago
Low's avatar Low

Subscribing. Right now 2 of my premium add-ons are broken in EE3.

       
Mark Croxton's avatar
Mark Croxton
319 posts
10 years ago
Mark Croxton's avatar Mark Croxton

Ok it looks like these hooks are missing from EE3:

Channel Entries API hooks

  • entry_submission_ready
  • entry_submission_start
  • entry_submission_end
  • entry_submission_absolute_end

Content Edit controller hooks

  • update_multi_entries_loop
  • update_multi_entries_start
  • delete_entries_loop
  • delete_entries_end
  • delete_entries_start
       
Mark Croxton's avatar
Mark Croxton
319 posts
10 years ago
Mark Croxton's avatar Mark Croxton

Just wanted to add: I rely on most of these hooks in Mustash, for cache-breaking when entries are added/edited/deleted. If you plan on replacing them with new hooks I do have a few specific suggestions to make them more useful than before.

       
Derek Jones's avatar
Derek Jones
7,561 posts
10 years ago
Derek Jones's avatar Derek Jones
If you plan on replacing them with new hooks I do have a few specific suggestions to make them more useful than before.

Please do, we don’t like dropping hooks into new code until we are able to see how it’s being used and what’s needed, so your input will help make that determination. Sorry for the confusion on those being removed, however we haven’t been using the Channel Entries API, so even though those hooks were in the code, they weren’t functional the entire developer preview, unless I’m mistaken?

       
Low's avatar
Low
407 posts
10 years ago
Low's avatar Low

I need the entry_submission_end hook (or something similar) for updating the search index and lexicon for Low Search. I also need it to add entries to a Low Reorder set. If it works like it did, that’s good enough for me.

I need the delete_entries_loop hook (or something similar) to remove entries from the Low Search index and Low Reorder sets. Again, if it works like it did, fine.

Next time, a heads up that hooks are no longer functioning rather than waiting for us to find out would be appreciated.

       
Mark Croxton's avatar
Mark Croxton
319 posts
10 years ago
Mark Croxton's avatar Mark Croxton

This is the Mustash plugin (below) for cache-breaking on edits to channel entries (whether in the control panel or a channel form).

The plugin takes entry data from the hook that was triggered and uses it to flush corresponding objects in the Stash cache by first parsing the markers in any cache-breaking rules attached to the plugin, and then searching the cache for matching variables.

I’d like the data about the entry that was edited to be provided in a complete and consistent format, with the same full set of fields available in the array or object passed. Then I don’t need to run additional queries to get metadata about the entry.

Furthermore, it would be useful if the ‘before edit’ and ‘after edit’ arrays of field data were provided to the hook called when an entry is updated.

Finally, in EE 2.x the ‘delete_entries_loop’ hook is called after the entry has been deleted, and no extra metadata about the deleted entry is provided to the hook - and so after deletion, it’s impossible to run a query to get that data. It would be great if either the meta data about the entry was retained and provided to the hook, or alternatively the hook was called before the entry is deleted.

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Stash_channel_entries_pi
 * Mustash cache-breaking plugin
 *
 * @package  Mustash
 * @author   Mark Croxton
 */

class Stash_channel_entries_pi extends Mustash_plugin {

 /**
  * Name
  *
  * @var  string
  * @access  public
  */
 public $name = 'Channel Entries';

 /**
  * Version
  *
  * @var  string
  * @access  public
  */
 public $version = '1.0.0';

 /**
  * Extension hook priority
  *
  * @var  integer
  * @access  public
  */
 public $priority = 10;

 /**
  * Extension hooks and associated markers
  *
  * @var  array
  * @access  protected
  */
 protected $hooks = array(

  '@all' => array(
   'channel_id',
   'channel_name',
   'entry_id',
  ), 
  'entry_submission_end' => array(
   'channel_id',
   'channel_name',
   'author_id',
   'entry_id',
   'url_title',
  ),
  'update_multi_entries_loop' => array(
   'channel_id',
   'channel_name',
   'author_id',
   'entry_id',
   'url_title',
  ),
  'delete_entries_loop' => array(
   'channel_id',
   'channel_name',
   'entry_id',
  )
 );

 /**
  * Constructor
  * 
  * @return void
  */
 public function __construct()
 {
  parent::__construct(); 
  ee()->load->model('mustash_channel_data');
 }

 /**
  * Set groups for this object
  *
  * @access protected
  * @return array
  */
 protected function set_groups()
 {
  return ee()->mustash_channel_data->get_channels();
 }

 /*
 ================================================================
 Hooks
 ================================================================
 */

 /**
  * Hook: entry_submission_end
  *
  * @access public
  * @param integer
  * @param array
  * @param array
  * @return void
  */
 public function entry_submission_end($entry_id, $meta, $data)
 {
  /* $meta:
  Array
  (
      [channel_id] => 7
      [author_id] => 2
      [site_id] => 1
      [ip_address] => 192.168.0.6
      [title] => Mike Swangard
      [url_title] => mike-swangard
      [entry_date] => 1363267553
      [edit_date] => 20130327162354
      [versioning_enabled] => y
      [year] => 2013
      [month] => 03
      [day] => 14
      [expiration_date] => 0
      [comment_expiration_date] => 0
      [sticky] => n
      [status] => open
      [allow_comments] => y
  )
  */

  // prep marker data
  $markers = array(
   'channel_id'  => $meta['channel_id'],
   'channel_name' => ee()->mustash_channel_data->get_channel_name($meta['channel_id']),
   'author_id'  => ee()->mustash_channel_data->get_author_id($entry_id),
      'entry_id'  => $entry_id,
      'url_title'  => $meta['url_title']
  );

  // flush cache
  $this->flush_cache(__FUNCTION__, $meta['channel_id'], $markers);
 }

 /**
  * Hook: update_multi_entries_loop
  *
  * @access public
  * @param integer
  * @param array
  * @return void
  */
 public function update_multi_entries_loop($entry_id, $data)
 {
  /* $data:
  Array
  (
      [title] => Blog entry 1
      [url_title] => blog-entry-1
      [entry_date] => 1357733074
      [edit_date] => 20130605171636
      [status] => open
      [sticky] => n
      [allow_comments] => y
      [year] => 2013
      [month] => 01
      [day] => 09
  )
  */

  // get missing channel data
  $channel = ee()->mustash_channel_data->get_channel($entry_id);

  // prep marker data
  $markers = array(
   'channel_id'  => $channel['channel_id'],
   'channel_name' => $channel['channel_name'],
   'author_id'  => ee()->mustash_channel_data->get_author_id($entry_id),
   'entry_id'  => $entry_id,
   'url_title'  => $data['url_title']
  );

  // flush cache
  $this->flush_cache(__FUNCTION__, $channel['channel_id'], $markers);
 }

 /**
  * Hook: delete_entries_loop
  *
  * @access public
  * @param integer
  * @param integer
  * @return void
  */
 public function delete_entries_loop($entry_id, $channel_id)
 {
  /*
  As this hook is called AFTER the entry has been deleted, 
  it is impossible to get any other data about the entry :(
  */

  $markers = array(
   'channel_id'  => $channel_id,
   'channel_name' => ee()->mustash_channel_data->get_channel_name($channel_id),
   'entry_id'  => $entry_id
  );

  // flush cache
  $this->flush_cache(__FUNCTION__, $channel_id, $markers);
 }
}
       
Derek Jones's avatar
Derek Jones
7,561 posts
10 years ago
Derek Jones's avatar Derek Jones

Next time, a heads up that hooks are no longer functioning rather than waiting for us to find out would be appreciated.

I don’t disagree, Low, we missed it because we were no longer using that code. Since evidently no developers worked on any add-ons surrounding publishing entries, it never bubbled up into our consciousness.

The point that I find a little frustrating is starting an open debate in the public chat. It’s not productive for any of us involved, nor for our mutual customers to start mud slinging and finger pointing. At the very least, you could share some blame. We’re working hard and doing our best, just like you.

My plan to prevent something like this happening in the future is to add some automated testing of the hooks, to make sure they are all actually executed in flow. We’re working towards 100% code coverage, but our new code has been the priority and we’ve not made it to hooks yet.

Thanks to both for the detailed feedback. We’ll wait for a few other devs to weigh in, speak to some at conference, and we can always chat in the Dev Chat as well. We’ll make sure and get your opinions on the hooks we propose before they ship, thanks!

       
Greg Ferrell's avatar
Greg Ferrell
102 posts
10 years ago
Greg Ferrell's avatar Greg Ferrell

This is a pretty huge issue for us, too. I couldn’t comment on this issue yet because i’ve not gotten to those addons which use them yet to know they were missing.

       
Derek Jones's avatar
Derek Jones
7,561 posts
10 years ago
Derek Jones's avatar Derek Jones

Any additional thoughts on what you’d like to see in the new hooks Greg?

       
Greg Ferrell's avatar
Greg Ferrell
102 posts
10 years ago
Greg Ferrell's avatar Greg Ferrell
Any additional thoughts on what you’d like to see in the new hooks Greg?

At the moment the best i can do is echo Mark and Low in saying: We use this functionality in multiple addons and not having them breaks those addons.

Channel Entries API hooks
  • entry_submission_ready
  • entry_submission_start
  • entry_submission_end
  • entry_submission_absolute_end
Content Edit controller hooks
  • update_multi_entries_loop
  • update_multi_entries_start
  • delete_entries_loop
  • delete_entries_end
  • delete_entries_start
       
Brian Litzinger's avatar
Brian Litzinger
711 posts
10 years ago
Brian Litzinger's avatar Brian Litzinger

yeah, I didn’t realize those were missing either. I’m still doing upgrades from the front-end of the site first, then tackling the CP, so I haven’t even gotten around to saving an entry. Those hooks are crucial to me too right now, however, I wonder if the new events would be able to replace them?

       
Pascal Kriete's avatar
Pascal Kriete
2,589 posts
10 years ago
Pascal Kriete's avatar Pascal Kriete

I played around a bit and we’ll be adding a few as part of our next release. Since this is an api change, semver dictates that we make it 3.1. We’ll have a short dev preview for it so we can nail down the parameters with real test cases. Please try to get your testing in early or let us know if that’s not possible.

Anyways, here are the hooks we’ll be adding:

before_channel_entry_insert
after_channel_entry_insert
before_channel_entry_update
after_channel_entry_update
before_channel_entry_save
after_channel_entry_save
before_channel_entry_delete
after_channel_entry_delete

These pretty much mirror the available model lifecycle events. They all receive the channel entry model object in question (object semantics, thus mutable between hooks), as well as the array version of that model (value semantics, thus immutable and guaranteed to match the real data sent). The update hooks also receive a third array that contains the original values of any items that were changed.

I also want to reinforce Brian’s comment. If your objects have a belongsTo relationship to a channel entry, you should use an inverse relationship instead of a delete hook. This will automatically cascade any deletion down to your model (triggering your model delete events if any are set up). It’s more consistent than a hook, and it considers the possibility of thousands of entries being deleted at once.

       
Low's avatar
Low
407 posts
10 years ago
Low's avatar Low

Sounds good, Pascal.

Can you also restore the category_save and category_delete hooks? Possibly in the same way you’re handling Channel Entries.

You might even consider adding similar hooks for any content type (Entries, Categories, Members, …).

FWIW, I need the Category hooks to trigger a search index update in Low Search. If there is another way of triggering that, I’m all ears.

       
Mark Croxton's avatar
Mark Croxton
319 posts
10 years ago
Mark Croxton's avatar Mark Croxton

The Members controller has some hooks already (although I can’t find cp_members_validate_members):

https://ellislab.com/expressionengine/user-guide/development/extension_hooks/cp/members/index.html

Would be great if, as Low suggests, these were all consistent with the Entries hooks proposed above.

An ‘after_category_reorder’ hook would also be very handy if you’re looking at categories too (hadn’t realised they were gone).

       
1 2

Reply

Sign In To Reply

ExpressionEngine Home Features Pro Contact Version Support
Learn Docs University Forums
Resources Support Add-Ons Partners Blog
Privacy Terms Trademark Use License

Packet Tide owns and develops ExpressionEngine. © Packet Tide, All Rights Reserved.