Hi,
I need to write a plugin that will send an email to users to notify them of new published articles. And while I'm a C++ developer since almost 30 years, I am not experienced with PHP.
This is what the plugin needs to do:
The manifest fileThe install script
This should also create the user field "Notify me of new content" in the database. However, it does not. The plugin file is correctly copied to /plugins/system/notifynewcontent, though.
The main plugin file
This should catch onContentAfterSave(), get a list of users that have the option "Notify me of new content" enabled, and then send the mail.As you can see, I have put in quite a lot of echo, log, and error_log calls. However, none of these messages ever appears in any of the log files or in the page source. In my Joomla configuration, I have enabled debugging.
I am stumped, because nothing seems to do anything. I guess (there doesn't seem to be much more than guessing with PHP) none of the plugin code is ever executed.
I would appreciate some help, and thank you in advance!
Cheers,
Frank
I need to write a plugin that will send an email to users to notify them of new published articles. And while I'm a C++ developer since almost 30 years, I am not experienced with PHP.
This is what the plugin needs to do:
- On installation, create a custom user field "Notify me of new articles". Should be a checkbox.
- When a new article is published, send an email to all users that have enabled "Notify me of new articles" in their profile.
The manifest file
Code:
<?xml version="1.0" encoding="utf-8"?><extension type="plugin" group="system" version="5.0" method="upgrade"> <name>PLG_SYSTEM_NOTIFYNEWCONTENT</name> <author>me</author> <creationDate>2024-06-06</creationDate> <copyright>(C) 2024 me</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <version>1.0.2</version> <description>PLG_SYSTEM_NOTIFYNEWCONTENT_DESC</description> <files> <filename plugin="notifynewcontent">plg_system_notifynewcontent.php</filename> <filename>install_script.php</filename> </files> <languages> <language tag="en-GB">language/en-GB/en-GB.plg_system_notifynewcontent.ini</language> <language tag="en-GB">language/en-GB/en-GB.plg_system_notifynewcontent.sys.ini</language> <language tag="de-DE">language/de-DE/de-DE.plg_system_notifynewcontent.ini</language> <language tag="de-DE">language/de-DE/de-DE.plg_system_notifynewcontent.sys.ini</language> </languages> <install> <scriptfile>install_script.php</scriptfile> </install></extension>
This should also create the user field "Notify me of new content" in the database. However, it does not. The plugin file is correctly copied to /plugins/system/notifynewcontent, though.
Code:
<?php// No direct accessdefined('_JEXEC') or die;use Joomla\CMS\Factory;use Joomla\CMS\Installer\InstallerScript;use Joomla\CMS\Language\Text;use Joomla\CMS\Log\Log;class PlgSystemNotifynewcontentInstallerScript extends InstallerScript{ public function preflight($type, $parent) { echo 'Install Preflight'; Log::add('Preflight action - Type: ' . $type, Log::NOTICE, 'install'); } public function postflight($type, $parent) { echo 'Install Postflight'; Log::add('Postflight action - Type: ' . $type, Log::NOTICE, 'install'); if ($type == 'install') { $this->addProfileField(); } elseif ($type == 'update') { // Actions to perform after update } elseif ($type == 'uninstall') { $this->removeProfileField(); } } public function uninstall($parent) { echo 'uninstall()'; Log::add('Uninstall action', Log::NOTICE, 'install'); $this->removeProfileField(); } protected function addProfileField() { echo 'addProfileField()'; Log::add('Adding profile field', Log::ERROR, 'install'); $db = Factory::getDbo(); $fieldTitle = Text::_('PLG_SYSTEM_NOTIFYNEWCONTENT_NOTIFY'); // Check if the field already exists $query = $db->getQuery(true) ->select('COUNT(*)') ->from($db->quoteName('#_fields')) ->where($db->quoteName('name') . ' = ' . $db->quote('notify_on_new_content')); $db->setQuery($query); if (!$db->loadResult()) { Log::add('Field does not exist, creating new field', Log::NOTICE, 'install'); // Add the field $query = $db->getQuery(true) ->insert($db->quoteName('#_fields')) ->columns(array( $db->quoteName('title'), $db->quoteName('name'), $db->quoteName('label'), $db->quoteName('type'), $db->quoteName('context'), $db->quoteName('state'), $db->quoteName('fieldparams'), $db->quoteName('created_time'), $db->quoteName('created_user_id') )) ->values( $db->quote($fieldTitle) . ', ' . $db->quote('notify_on_new_content') . ', ' . $db->quote($fieldTitle) . ', ' . $db->quote('radio') . ', ' . $db->quote('com_users.user') . ', ' . 1 . ', ' . $db->quote(json_encode(array( 'default' => '0', 'options' => array( array('value' => '1', 'text' => 'Yes'), array('value' => '0', 'text' => 'No') ) ))) . ', ' . $db->quote(Factory::getDate()->toSql()) . ', ' . $db->quote(Factory::getUser()->id) ); $db->setQuery($query); try { $db->execute(); Log::add('Field created successfully', Log::NOTICE, 'install'); } catch (Exception $e) { Log::add('Error creating field: ' . $e->getMessage(), Log::ERROR, 'install'); } } else { Log::add('Field already exists', Log::NOTICE, 'install'); } } protected function removeProfileField() { echo 'removeProfileField()'; Log::add('Removing profile field', Log::NOTICE, 'install'); $db = Factory::getDbo(); $query = $db->getQuery(true) ->delete($db->quoteName('#_fields')) ->where($db->quoteName('name') . ' = ' . $db->quote('notify_on_new_content')); $db->setQuery($query); try { $db->execute(); Log::add('Field removed successfully', Log::NOTICE, 'install'); } catch (Exception $e) { Log::add('Error removing field: ' . $e->getMessage(), Log::ERROR, 'install'); } }}
This should catch onContentAfterSave(), get a list of users that have the option "Notify me of new content" enabled, and then send the mail.
Code:
<?php// No direct accessdefined('_JEXEC') or die;use Joomla\CMS\Plugin\CMSPlugin;use Joomla\CMS\Factory;use Joomla\CMS\Language\Text;use Joomla\CMS\Uri\Uri;use Joomla\CMS\Router\Route;class PlgSystemNotifynewcontent extends CMSPlugin{ protected $app; protected $db; public function __construct(&$subject, $config) { parent::__construct($subject, $config); $this->db = Factory::getDbo(); } public function onContentAfterSave($context, $article, $isNew) { error_log('onContentAfterSave triggered'); if ($context == 'com_content.article' && $isNew) { error_log('New article detected'); $this->notifyUsers($article); } } protected function notifyUsers($article) { // Get the field ID for 'notify_on_new_content' $query = $this->db->getQuery(true) ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#_fields')) ->where($this->db->quoteName('name') . ' = ' . $this->db->quote('notify_on_new_content')); $this->db->setQuery($query); $fieldId = $this->db->loadResult(); if (!$fieldId) { error_log('Field "notify_on_new_content" not found.'); return; } // Get all users with the "Notify on new content" enabled $query = $this->db->getQuery(true) ->select($this->db->quoteName(array('u.email', 'u.name'))) ->from($this->db->quoteName('#_users', 'u')) ->join('INNER', $this->db->quoteName('#_fields_values', 'fv') . ' ON ' . $this->db->quoteName('u.id') . ' = ' . $this->db->quoteName('fv.item_id')) ->where($this->db->quoteName('fv.field_id') . ' = ' . (int) $fieldId) ->where($this->db->quoteName('fv.value') . ' = ' . $this->db->quote('1')); $this->db->setQuery($query); $users = $this->db->loadObjectList(); error_log('Users to notify: ' . count($users)); // Get the category name $categoryId = $article->catid; $categoryQuery = $this->db->getQuery(true) ->select($this->db->quoteName('title')) ->from($this->db->quoteName('#_categories')) ->where($this->db->quoteName('id') . ' = ' . (int) $categoryId); $this->db->setQuery($categoryQuery); $categoryName = $this->db->loadResult(); // Prepare email subject and body $subject = Text::_('PLG_SYSTEM_NOTIFYNEWCONTENT_EMAIL_SUBJECT'); $bodyTemplate = Text::_('PLG_SYSTEM_NOTIFYNEWCONTENT_EMAIL_BODY'); // Generate SEF URL $articleLink = Route::_( 'index.php?option=com_content&view=article&id=' . $article->id . ':' . $article->alias . '&catid=' . $article->catid . '&Itemid=' . $article->params->get('item_id') , false); // Format the publish date $publishDate = (new \Joomla\CMS\Date\Date($article->publish_up))->format('d.m.Y'); $body = str_replace( array('{ARTICLE_TITLE}', '{ARTICLE_CATEGORY}', '{ARTICLE_PUBLISH_DATE}', '{ARTICLE_LINK}'), array($article->title, $categoryName, $publishDate, Uri::root() . $articleLink), $bodyTemplate ); error_log('Email body: ' . $body); // Send email to each user foreach ($users as $user) { $mail = Factory::getMailer(); $mail->addRecipient($user->email); $mail->setSubject($subject); $mail->setBody($body); $mail->Send(); error_log('Email sent to: ' . $user->email); } }}
I am stumped, because nothing seems to do anything. I guess (there doesn't seem to be much more than guessing with PHP) none of the plugin code is ever executed.
I would appreciate some help, and thank you in advance!
Cheers,
Frank
Statistics: Posted by frankw80 — Thu Jun 06, 2024 8:37 am