If you have questions or other issues feel free to ask.
Please don't be confused, my Plugins handle/name is "Test" because I only use it for these purposes.. So whenever you see the name "Test" you know you have to rename it
This is your plugins init function
/**
* Called after the plugin class is instantiated; do any one-time initialization here such as hooks and events:
* @return mixed
*/
public function init()
{
parent::init();
craft()->on('entries.onBeforeSaveEntry', function(Event $event)
{
// trigger only when entries are changed not when created
if(!$event->params['isNewEntry']){
/** @var EntryModel $entry */
$entry = $event->params['entry'];
// create your logic to check if it is the correct entry...
// you should check for your section here otherwise you'll send a mail for all updates^^
// I just used the handle pages in my test system
if($entry->getSection()->handle === "pages"){
// next: fetch all user related to the entry...
// since I don't know your entire fields, you have to implement the logic
// to fetch users from entries that are related to the entry yourself
// if you need help just ask
$criteria = craft()->elements->getCriteria(ElementType::User);
$criteria->relatedTo($entry);
/** @var UserModel $user */
foreach( $criteria as $user){
// create a new entry in the database
$email = new Test_EmailRecord();
$email->entryId = $entry->id;
$email->email = $user->email;
$email->save();
}
}
}
});
}
And you have to create the following record
namespace Craft;
class Test_EmailRecord extends BaseRecord
{
public function getTableName()
{
return 'cron_mails';
}
protected function defineAttributes()
{
return array(
// you could store the user Id here too, but this way
// you can send the mail to non users too
'email' => AttributeType::String,
'entryId' => array(AttributeType::Number),
);
}
// you could - if you want - create relations here..
// https://craftcms.com/docs/plugins/records#defining-relations
// but since it's only an example and not needed I skipped that part
}
And you need this in your controller
/**
* Cronjob to send emails... you can activate it every X hours
* or once per day or whatever you want
* when this function is trigger a specific number of mails will be send
* their entries in the database will be deleted until there are no rows in the
* table
*/
public function actionSendMails()
{
// fetch mails with limit.. insert your limit here.. I would suggest to fetch 20-50
// entries per trigger depending on how often it should run
$emails = Test_EmailRecord::model()->findAllBySql('select * from craft_cron_mails LIMIT 1');
if (is_array($emails) && count($emails)) {
foreach ($emails as $email) {
/** @var UserModel $user */
$user = craft()->users->getUserByEmail($email->email);
// do your logic if no user is found..
// of course you could store the user Id rather than the email in the database table
// but this way you can send the mail to non users too if you like
if (!$user) {
// you can just remove that part
// I just wanted to show you could create an array with defaults here
// if the user is not registered
$user = array(/* fill some placeholders for your twig template */);
}
// prepare templates, you can address each user personally with a hello Mr {{ user.name }}
// the entry {{ entry.title }} was edited and such...
$message = craft()->templates->render('path/to/template.twig', array(
'user' => $user,
'entry' => craft()->elements->getElementById($email->entryId)
));
if ($this->sendMail($message, "The post was edited", $user->email)) {
//remove the column if the mail was send
$email->delete();
}
}
}
}
/**
* This function sends the mail, it usually belongs to a service
* but to make it easier I'll just leave it here
*
* @param $message
* @param $subject
* @param null $mail
* @return bool
*/
public function sendMail($message, $subject, $mail = null)
{
$errors = false;
$adminEmail = craft()->systemSettings->getSetting('email', 'emailAddress');
$email = new EmailModel();
$email->fromEmail = $adminEmail;
$email->replyTo = $adminEmail;
$email->sender = $adminEmail;
$email->fromName = craft()->getSiteName();
$email->toEmail = $mail;
$email->subject = $subject;
$email->body = $message;
if (!craft()->email->sendEmail($email)) {
$errors = true;
}
return $errors;
}
entry.onUpdate
method and send a mail to all users. That would be only a few lines (I'll write them) but if you think there could be 20+ people in one entry with frequent updates you have to collect all mails in a table and create a cron job to send them. It's easy but requires much more code (when you use craft 2,with craft 3 it's less). – Robin Schambach Oct 22 '17 at 13:40