From faa2e43e3716b2c921538518b77701223a2d4626 Mon Sep 17 00:00:00 2001 From: Ortwin Pinke Date: Sat, 26 Oct 2019 14:35:06 +0200 Subject: [PATCH] Add files via upload --- cl_plugin.xml | 82 ++ classes/class.newsletter.groups.php | 288 +++++ classes/class.newsletter.jobs.php | 483 ++++++++ classes/class.newsletter.logs.php | 243 ++++ classes/class.newsletter.php | 998 +++++++++++++++ classes/class.newsletter.recipients.php | 248 ++++ includes/config.autoloader.php | 17 + includes/config.plugin.php | 35 + includes/include.newsletter_edit.php | 556 +++++++++ includes/include.newsletter_edit_message.php | 257 ++++ includes/include.newsletter_jobs_details.php | 379 ++++++ includes/include.newsletter_jobs_menu.php | 344 ++++++ includes/include.newsletter_jobs_subnav.php | 67 + includes/include.newsletter_left_top.php | 960 +++++++++++++++ includes/include.newsletter_menu.php | 367 ++++++ includes/include.newsletter_subnav.php | 65 + includes/include.recipients.group.subnav.php | 72 ++ includes/include.recipients.group_edit.php | 568 +++++++++ includes/include.recipients.group_menu.php | 234 ++++ includes/include.recipients_edit.php | 246 ++++ includes/include.recipients_import.php | 360 ++++++ includes/include.recipients_menu.php | 288 +++++ locale/cl_newsletter.pot | 1055 ++++++++++++++++ locale/de_DE/LC_MESSAGES/cl_newsletter.mo | Bin 0 -> 19185 bytes locale/de_DE/LC_MESSAGES/cl_newsletter.po | 1162 ++++++++++++++++++ locale/potfiles.txt | 21 + plugin_install.sql | 114 ++ plugin_uninstall.sql | 12 + xml/lang_de_DE.xml | 10 + xml/lang_en_EN.xml | 10 + xml/lang_en_US.xml | 10 + xml/lang_fr_FR.xml | 10 + xml/lang_it_IT.xml | 10 + xml/lang_nl_NL.xml | 10 + 34 files changed, 9581 insertions(+) create mode 100644 cl_plugin.xml create mode 100644 classes/class.newsletter.groups.php create mode 100644 classes/class.newsletter.jobs.php create mode 100644 classes/class.newsletter.logs.php create mode 100644 classes/class.newsletter.php create mode 100644 classes/class.newsletter.recipients.php create mode 100644 includes/config.autoloader.php create mode 100644 includes/config.plugin.php create mode 100644 includes/include.newsletter_edit.php create mode 100644 includes/include.newsletter_edit_message.php create mode 100644 includes/include.newsletter_jobs_details.php create mode 100644 includes/include.newsletter_jobs_menu.php create mode 100644 includes/include.newsletter_jobs_subnav.php create mode 100644 includes/include.newsletter_left_top.php create mode 100644 includes/include.newsletter_menu.php create mode 100644 includes/include.newsletter_subnav.php create mode 100644 includes/include.recipients.group.subnav.php create mode 100644 includes/include.recipients.group_edit.php create mode 100644 includes/include.recipients.group_menu.php create mode 100644 includes/include.recipients_edit.php create mode 100644 includes/include.recipients_import.php create mode 100644 includes/include.recipients_menu.php create mode 100644 locale/cl_newsletter.pot create mode 100644 locale/de_DE/LC_MESSAGES/cl_newsletter.mo create mode 100644 locale/de_DE/LC_MESSAGES/cl_newsletter.po create mode 100644 locale/potfiles.txt create mode 100644 plugin_install.sql create mode 100644 plugin_uninstall.sql create mode 100644 xml/lang_de_DE.xml create mode 100644 xml/lang_en_EN.xml create mode 100644 xml/lang_en_US.xml create mode 100644 xml/lang_fr_FR.xml create mode 100644 xml/lang_it_IT.xml create mode 100644 xml/lang_nl_NL.xml diff --git a/cl_plugin.xml b/cl_plugin.xml new file mode 100644 index 0000000..544ca80 --- /dev/null +++ b/cl_plugin.xml @@ -0,0 +1,82 @@ + + + + ConLite Newsletter + cl_newsletter + 45D7F1F3-41E9-57BC-8987-C0550B3B07B8 + ConLite Newsletter System + ConLite Team + ConLite Team + cl_newsletter@conlite.org + https://conlite.org + 1.0.0 + + + + + + + news + news_edit + news_edittpl + news_editcontent + news_jobs + recipients + recipients_import + recipientgroups + + + news_save + news_create + news_delete + news_duplicate + news_add_job + news_send_test + news_job_delete + news_job_details + news_job_detail_delete + news_html_settings + news_job_run + recipients_save + recipients_create + recipients_delete + recipientgroup_delete + recipientgroup_create + recipientgroup_recipient_delete + recipientgroup_save_group + recipients_purge + recipients_import + recipients_import_exec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/classes/class.newsletter.groups.php b/classes/class.newsletter.groups.php new file mode 100644 index 0000000..7c2a5a2 --- /dev/null +++ b/classes/class.newsletter.groups.php @@ -0,0 +1,288 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01 + * modified 2008-06-30, Dominik Ziegler, add security fix + * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting + * + * $Id: class.newsletter.groups.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +/** + * Recipient group management class + */ +class RecipientGroupCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news_groups"], "idnewsgroup"); + $this->_setItemClass("RecipientGroup"); + } + + /** + * Creates a new group + * @param $groupname string Specifies the groupname + * @param $defaultgroup integer Specfies, if group is default group (optional) + */ + public function create($groupname, $defaultgroup = 0) { + global $client, $lang; + + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + $group = new RecipientGroup(); + + #$_arrInFilters = array('urlencode', 'clHtmlSpecialChars', 'addslashes'); + + $mangledGroupName = $group->_inFilter($groupname); + $this->setWhere("idclient", $client); + $this->setWhere("idlang", $lang); + $this->setWhere("groupname", $mangledGroupName); + $this->query(); + + if ($obj = $this->next()) { + $groupname = $groupname . md5(rand()); + } + + $item = parent::createNewItem(); + + $item->set("idclient", $client); + $item->set("idlang", $lang); + $item->set("groupname", $groupname); + $item->set("defaultgroup", $defaultgroup); + $item->store(); + + return $item; + } + + /** + * Overridden delete method to remove groups from groupmember table + * before deleting group + * + * @param $itemID int specifies the newsletter recipient group + */ + public function delete($itemID) { + $oAssociations = new RecipientGroupMemberCollection; + $oAssociations->setWhere("idnewsgroup", $itemID); + $oAssociations->query(); + + while ($oItem = $oAssociations->next()) { + $oAssociations->delete($oItem->get("idnewsgroupmember")); + } + parent::delete($itemID); + } + +} + +/** + * Single RecipientGroup Item + */ +class RecipientGroup extends Item { + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news_groups"], "idnewsgroup"); + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + + /** + * Overriden store() method to ensure, that there is only one default group + * */ + public function store() { + global $client, $lang; + + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + if ($this->get("defaultgroup") == 1) { + $oItems = new RecipientGroupCollection(); + $oItems->setWhere("idclient", $client); + $oItems->setWhere("idlang", $lang); + $oItems->setWhere("defaultgroup", 1); + $oItems->setWhere("idnewsgroup", $this->get("idnewsgroup"), "<>"); + $oItems->query(); + + while ($oItem = $oItems->next()) { + $oItem->set("defaultgroup", 0); + $oItem->store(); + } + } + parent::store(); + } + +} + +/** + * Recipient group member management class + */ +class RecipientGroupMemberCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news_groupmembers"], "idnewsgroupmember"); + $this->_setJoinPartner('RecipientGroupCollection'); + $this->_setJoinPartner('RecipientCollection'); + $this->_setItemClass("RecipientGroupMember"); + } + + /** + * Creates a new association + * @param $idrecipientgroup int specifies the newsletter group + * @param $idrecipient int specifies the newsletter user + */ + public function create($idrecipientgroup, $idrecipient) { + $idrecipientgroup = Contenido_Security::toInteger($idrecipientgroup); + $idrecipient = Contenido_Security::toInteger($idrecipient); + + $this->setWhere("idnewsgroup", $idrecipientgroup); + $this->setWhere("idnewsrcp", $idrecipient); + $this->query(); + + if ($this->next()) { + return false; + } + + $oItem = parent::create(); + + $oItem->set("idnewsrcp", $idrecipient); + $oItem->set("idnewsgroup", $idrecipientgroup); + $oItem->store(); + + return $oItem; + } + + /** + * Removes an association + * @param $idrecipientgroup int specifies the newsletter group + * @param $idrecipient int specifies the newsletter user + */ + public function remove($idrecipientgroup, $idrecipient) { + $idrecipientgroup = Contenido_Security::toInteger($idrecipientgroup); + $idrecipient = Contenido_Security::toInteger($idrecipient); + + $this->setWhere("idnewsgroup", $idrecipientgroup); + $this->setWhere("idnewsrcp", $idrecipient); + $this->query(); + + if ($oItem = $this->next()) { + $this->delete($oItem->get("idnewsgroupmember")); + } + } + + /** + * Removes all associations from any newsletter group + * @param $idrecipient int specifies the newsletter recipient + */ + public function removeRecipientFromGroups($idrecipient) { + $idrecipient = Contenido_Security::toInteger($idrecipient); + + $this->setWhere("idnewsrcp", $idrecipient); + $this->query(); + + while ($oItem = $this->next()) { + $this->delete($oItem->get("idnewsgroupmember")); + } + } + + /** + * Removes all associations of a newsletter group + * @param $idgroup int specifies the newsletter recipient group + */ + public function removeGroup($idgroup) { + $idgroup = Contenido_Security::toInteger($idgroup); + + $this->setWhere("idnewsgroup", $idgroup); + $this->query(); + + while ($oItem = $this->next()) { + $this->delete($oItem->get("idnewsgroupmember")); + } + } + + /** + * Returns all recipients in a single group + * @param $idrecipientgroup int specifies the newsletter group + * @param $asObjects boolean specifies if the function should return objects + * @return array RecipientRecipient items + */ + public function getRecipientsInGroup($idrecipientgroup, $asObjects = true) { + $idrecipientgroup = Contenido_Security::toInteger($idrecipientgroup); + + $this->setWhere("idnewsgroup", $idrecipientgroup); + $this->query(); + + $aObjects = array(); + + while ($oItem = $this->next()) { + if ($asObjects) { + $oRecipient = new Recipient(); + $oRecipient->loadByPrimaryKey($oItem->get("idnewsrcp")); + + $aObjects[] = $oRecipient; + } else { + $aObjects[] = $oItem->get("idnewsrcp"); + } + } + + return ($aObjects); + } + +} + +/** + * Single RecipientGroup Item + */ +class RecipientGroupMember extends Item { + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news_groupmembers"], "idnewsgroupmember"); + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + +} diff --git a/classes/class.newsletter.jobs.php b/classes/class.newsletter.jobs.php new file mode 100644 index 0000000..d42a2b7 --- /dev/null +++ b/classes/class.newsletter.jobs.php @@ -0,0 +1,483 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01 + * modified 2008-06-30, Dominik Ziegler, add security fix + * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting + * + * $Id: class.newsletter.jobs.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +/** + * Collection management class + */ +class cNewsletterJobCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news_jobs"], "idnewsjob"); + $this->_setItemClass("cNewsletterJob"); + } + + /** + * Creates a newsletter job + * @param $name string Specifies the name of the newsletter, the same name may be used more than once + * @param $idnews integer Newsletter id + */ + public function create($iIDNews, $iIDCatArt, $sName = "") { + global $client, $lang, $cfg, $cfgClient, $auth; + + $oNewsletter = new Newsletter; + if ($oNewsletter->loadByPrimaryKey($iIDNews)) { + $iIDNews = Contenido_Security::toInteger($iIDNews); + $iIDCatArt = Contenido_Security::toInteger($iIDCatArt); + $lang = Contenido_Security::toInteger($lang); + $client = Contenido_Security::toInteger($client); + $sName = Contenido_Security::escapeDB($sName, null); + + $oItem = parent::createNewItem(); + + $oItem->set("idnews", $iIDNews); + $oItem->set("idclient", $client); + $oItem->set("idlang", $lang); + + if ($sName == "") { + $oItem->set("name", $oNewsletter->get("name")); + } else { + $oItem->set("name", $sName); + } + $oItem->set("type", $oNewsletter->get("type")); + $oItem->set("use_cronjob", $oNewsletter->get("use_cronjob")); + + $oLang = new cApiLanguage($lang); + $oItem->set("encoding", $oLang->get("encoding")); + unset($oLang); + + $oItem->set("idart", $oNewsletter->get("idart")); + $oItem->set("subject", $oNewsletter->get("subject")); + + // Precompile messages + $sPath = $cfgClient[$client]["path"]["htmlpath"] . "front_content.php?changelang=" . $lang . "&idcatart=" . $iIDCatArt . "&"; + + $sMessageText = $oNewsletter->get("message"); + + // Preventing double lines in mail, you may wish to disable this function on windows servers + if (!getSystemProperty("newsletter", "disable-rn-replacement")) { + $sMessageText = str_replace("\r\n", "\n", $sMessageText); + } + + $oNewsletter->_replaceTag($sMessageText, false, "unsubscribe", $sPath . "unsubscribe={KEY}"); + $oNewsletter->_replaceTag($sMessageText, false, "change", $sPath . "change={KEY}"); + $oNewsletter->_replaceTag($sMessageText, false, "stop", $sPath . "stop={KEY}"); + $oNewsletter->_replaceTag($sMessageText, false, "goon", $sPath . "goon={KEY}"); + + $oItem->set("message_text", $sMessageText); + + if ($oNewsletter->get("type") == "text") { + // Text newsletter, no html message + $sMessageHTML = ""; + } else { + // HTML newsletter, get article content + $sMessageHTML = $oNewsletter->getHTMLMessage(); + + if ($sMessageHTML) { + $oNewsletter->_replaceTag($sMessageHTML, true, "name", "MAIL_NAME"); + $oNewsletter->_replaceTag($sMessageHTML, true, "number", "MAIL_NUMBER"); + $oNewsletter->_replaceTag($sMessageHTML, true, "date", "MAIL_DATE"); + $oNewsletter->_replaceTag($sMessageHTML, true, "time", "MAIL_TIME"); + + $oNewsletter->_replaceTag($sMessageHTML, true, "unsubscribe", $sPath . "unsubscribe={KEY}"); + $oNewsletter->_replaceTag($sMessageHTML, true, "change", $sPath . "change={KEY}"); + $oNewsletter->_replaceTag($sMessageHTML, true, "stop", $sPath . "stop={KEY}"); + $oNewsletter->_replaceTag($sMessageHTML, true, "goon", $sPath . "goon={KEY}"); + + // Replace plugin tags by simple MAIL_ tags + if (getSystemProperty("newsletter", "newsletter-recipients-plugin") == "true") { + if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $sPlugin) { + plugin_include("recipients", $sPlugin . "/" . $sPlugin . ".php"); + if (function_exists("recipients_" . $sPlugin . "_wantedVariables")) { + $aPluginVars = array(); + $aPluginVars = call_user_func("recipients_" . $sPlugin . "_wantedVariables"); + + foreach ($aPluginVars as $sPluginVar) { + $oNewsletter->_replaceTag($sMessageHTML, true, $sPluginVar, "MAIL_" . strtoupper($sPluginVar)); + } + } + } + } + } + } else { + // There was a problem getting html message (maybe article deleted) + // Cancel job generation + return false; + } + } + + $oItem->set("message_html", $sMessageHTML); + + $oItem->set("newsfrom", $oNewsletter->get("newsfrom")); + if ($oNewsletter->get("newsfromname") == "") { + $oItem->set("newsfromname", $oNewsletter->get("newsfrom")); + } else { + $oItem->set("newsfromname", $oNewsletter->get("newsfromname")); + } + $oItem->set("newsdate", date("Y-m-d H:i:s"), false); //$oNewsletter->get("newsdate")); + $oItem->set("dispatch", $oNewsletter->get("dispatch")); + $oItem->set("dispatch_count", $oNewsletter->get("dispatch_count")); + $oItem->set("dispatch_delay", $oNewsletter->get("dispatch_delay")); + + // Store "send to" info in serialized array (just info) + $aSendInfo = array(); + $aSendInfo[] = $oNewsletter->get("send_to"); + + switch ($oNewsletter->get("send_to")) { + case "selection": + $oGroups = new RecipientGroupCollection; + $oGroups->setWhere("idnewsgroup", unserialize($oNewsletter->get("send_ids")), "IN"); + $oGroups->setOrder("groupname"); + $oGroups->query(); + #$oGroups->select("idnewsgroup IN ('" . implode("','", unserialize($oNewsletter->get("send_ids"))) . "')", "", "groupname"); + + while ($oGroup = $oGroups->next()) { + $aSendInfo[] = $oGroup->get("groupname"); + } + + unset($oGroup); + unset($oGroups); + break; + case "single": + if (is_numeric($oNewsletter->get("send_ids"))) { + $oRcp = new Recipient($oNewsletter->get("send_ids")); + + if ($oRcp->get("name") == "") { + $aSendInfo[] = $oRcp->get("email"); + } else { + $aSendInfo[] = $oRcp->get("name"); + } + $aSendInfo[] = $oRcp->get("email"); + + unset($oRcp); + } + break; + default: + } + $oItem->set("send_to", serialize($aSendInfo), false); + + $oItem->set("created", date("Y-m-d H:i:s"), false); + $oItem->set("author", $auth->auth["uid"]); + $oItem->set("authorname", $auth->auth["uname"]); + unset($oNewsletter); // Not needed anymore + // Adds log items for all recipients and returns recipient count + $oLogs = new cNewsletterLogCollection(); + $iRecipientCount = $oLogs->initializeJob($oItem->get($oItem->primaryKey), $iIDNews); + unset($oLogs); + + $oItem->set("rcpcount", $iRecipientCount); + $oItem->set("sendcount", 0); + $oItem->set("status", 1); // Waiting for sending; note, that status will be set to 9, if $iRecipientCount = 0 in store() method + + $oItem->store(); + + return $oItem; + } else { + return false; + } + } + + /** + * Overridden delete method to remove job details (logs) from newsletter logs table + * before deleting newsletter job + * + * @param $iItemID int specifies the frontend user group + */ + public function delete($iItemID) { + $oLogs = new cNewsletterLogCollection(); + $oLogs->delete($iItemID); + + parent::delete($iItemID); + } + +} + +/** + * Single NewsletterJob Item + */ +class cNewsletterJob extends Item { + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news_jobs"], "idnewsjob"); + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + + public function runJob() { + global $cfg, $recipient; + + $iCount = 0; + if ($this->get("status") == 2) { + // Job is currently running, check start time and restart if + // started 5 minutes ago + $dStart = strtotime($this->get("started")); + $dNow = time(); + + if (($dNow - $dStart) > (5 * 60)) { + $this->set("status", 1); + $this->set("started", "0000-00-00 00:00:00", false); + + $oLogs = new cNewsletterLogCollection(); + $oLogs->setWhere("idnewsjob", $this->get($this->primaryKey)); + $oLogs->setWhere("status", "sending"); + $oLogs->query(); + + while ($oLog = $oLogs->next()) { + $oLog->set("status", "error (sending)"); + $oLog->store(); + } + } + } + + if ($this->get("status") == 1) { + // Job waiting for sending + $this->set("status", 2); + $this->set("started", date("Y-m-d H:i:s"), false); + $this->store(); + + // Initialization + $aMessages = array(); + + $oLanguage = new cApiLanguage($this->get("idlang")); + $sFormatDate = $oLanguage->getProperty("dateformat", "date"); + $sFormatTime = $oLanguage->getProperty("dateformat", "time"); + unset($oLanguage); + + if ($sFormatDate == "") { + $sFormatDate = "%d.%m.%Y"; + } + if ($sFormatTime == "") { + $sFormatTime = "%H:%M"; + } + + // Get newsletter data + $sFrom = $this->get("newsfrom"); + $sFromName = $this->get("newsfromname"); + $sSubject = $this->get("subject"); + $sMessageText = $this->get("message_text"); + $sMessageHTML = $this->get("message_html"); + $dNewsDate = strtotime($this->get("newsdate")); + $sEncoding = $this->get("encoding"); + $bIsHTML = false; + if ($this->get("type") == "html" && $sMessageHTML != "") { + $bIsHTML = true; + } + + $bDispatch = false; + if ($this->get("dispatch") == 1) { + $bDispatch = true; + } + + // Single replacements + // Replace message tags (text message) + $sMessageText = str_replace("MAIL_DATE", strftime($sFormatDate, $dNewsDate), $sMessageText); + $sMessageText = str_replace("MAIL_TIME", strftime($sFormatTime, $dNewsDate), $sMessageText); + $sMessageText = str_replace("MAIL_NUMBER", $this->get("rcpcount"), $sMessageText); + + // Replace message tags (html message) + if ($bIsHTML) { + $sMessageHTML = str_replace("MAIL_DATE", strftime($sFormatDate, $dNewsDate), $sMessageHTML); + $sMessageHTML = str_replace("MAIL_TIME", strftime($sFormatTime, $dNewsDate), $sMessageHTML); + $sMessageHTML = str_replace("MAIL_NUMBER", $this->get("rcpcount"), $sMessageHTML); + } + + // Enabling plugin interface + $bPluginEnabled = false; + if (getSystemProperty("newsletter", "newsletter-recipients-plugin") == "true") { + $bPluginEnabled = true; + $aPlugins = array(); + + if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $sPlugin) { + plugin_include("recipients", $sPlugin . "/" . $sPlugin . ".php"); + if (function_exists("recipients_" . $sPlugin . "_wantedVariables")) { + $aPlugins[$sPlugin] = call_user_func("recipients_" . $sPlugin . "_wantedVariables"); + } + } + } + } + + // Get recipients (from log table) + if (!is_object($oLogs)) { + $oLogs = new cNewsletterLogCollection; + } else { + $oLogs->resetQuery(); + } + $oLogs->setWhere("idnewsjob", $this->get($this->primaryKey)); + $oLogs->setWhere("status", "pending"); + + if ($bDispatch) { + $oLogs->setLimit(0, $this->get("dispatch_count")); + } + + $oLogs->query(); + while ($oLog = $oLogs->next()) { + $iCount++; + $oLog->set("status", "sending"); + $oLog->store(); + + $sRcpMsgText = $sMessageText; + $sRcpMsgHTML = $sMessageHTML; + + $sKey = $oLog->get("rcphash"); + $sEMail = $oLog->get("rcpemail"); + $bSendHTML = false; + if ($oLog->get("rcpnewstype") == 1) { + $bSendHTML = true; // Recipient accepts html newsletter + } + + if (strlen($sKey) == 30) { // Prevents sending without having a key + $sRcpMsgText = str_replace("{KEY}", $sKey, $sRcpMsgText); + $sRcpMsgText = str_replace("MAIL_MAIL", $sEMail, $sRcpMsgText); + $sRcpMsgText = str_replace("MAIL_NAME", $oLog->get("rcpname"), $sRcpMsgText); + + // Replace message tags (html message) + if ($bIsHTML && $bSendHTML) { + $sRcpMsgHTML = str_replace("{KEY}", $sKey, $sRcpMsgHTML); + $sRcpMsgHTML = str_replace("MAIL_MAIL", $sEMail, $sRcpMsgHTML); + $sRcpMsgHTML = str_replace("MAIL_NAME", $oLog->get("rcpname"), $sRcpMsgHTML); + } + + if ($bPluginEnabled) { + // Don't change name of $recipient variable as it is used in plugins! + $recipient = new Recipient(); + $recipient->loadByPrimaryKey($oLog->get("idnewsrcp")); + + foreach ($aPlugins as $sPlugin => $aPluginVar) { + foreach ($aPluginVar as $sPluginVar) { + // Replace tags in text message + $sRcpMsgText = str_replace("MAIL_" . strtoupper($sPluginVar), call_user_func("recipients_" . $sPlugin . "_getvalue", $sPluginVar), $sRcpMsgText); + + // Replace tags in html message + if ($bIsHTML && $bSendHTML) { + $sRcpMsgHTML = str_replace("MAIL_" . strtoupper($sPluginVar), call_user_func("recipients_" . $sPlugin . "_getvalue", $sPluginVar), $sRcpMsgHTML); + } + } + } + unset($recipient); + } + + $oMail = new PHPMailer(); + $oMail->CharSet = $sEncoding; + $oMail->IsHTML($bIsHTML && $bSendHTML); + $oMail->From = $sFrom; + $oMail->FromName = $sFromName; + $oMail->AddAddress($sEMail); + $oMail->Mailer = "mail"; + $oMail->Subject = $sSubject; + + if ($bIsHTML && $bSendHTML) { + $oMail->Body = $sRcpMsgHTML; + $oMail->AltBody = $sRcpMsgText . "\n\n"; + } else { + $oMail->Body = $sRcpMsgText . "\n\n"; + } + + if ($oMail->Send()) { + $oLog->set("status", "successful"); + $oLog->set("sent", date("Y-m-d H:i:s"), false); + } else { + $oLog->set("status", "error (sending)"); + } + } else { + $oLog->set("status", "error (key)"); + } + $oLog->store(); + } + + $this->set("sendcount", $this->get("sendcount") + $iCount); + + if ($iCount == 0 || !$bDispatch) { + // No recipients remaining, job finished + $this->set("status", 9); + $this->set("finished", date("Y-m-d H:i:s"), false); + } else if ($bDispatch) { + // Check, if there are recipients remaining - stops job faster + $oLogs->resetQuery(); + $oLogs->setWhere("idnewsjob", $this->get($this->primaryKey)); + $oLogs->setWhere("status", "pending"); + $oLogs->setLimit(0, $this->get("dispatch_count")); + $oLogs->query(); + + If ($oLogs->next()) { + // Remaining recipients found, set job back to pending + $this->set("status", 1); + $this->set("started", "0000-00-00 00:00:00", false); + } else { + // No remaining recipients, job finished + $this->set("status", 9); + $this->set("finished", date("Y-m-d H:i:s"), false); + } + } else { + // Set job back to pending + $this->set("status", 1); + $this->set("started", "0000-00-00 00:00:00", false); + } + $this->store(); + } + + return $iCount; + } + + /** + * Overriden store() method to set status to finished if rcpcount is 0 + */ + public function store() { + if ($this->get("rcpcount") == 0) { + // No recipients, job finished + $this->set("status", 9); + if ($this->get("started") == "0000-00-00 00:00:00") { + $this->set("started", date("Y-m-d H:i:s"), false); + } + $this->set("finished", date("Y-m-d H:i:s"), false); + } + + parent::store(); + } + +} + +?> \ No newline at end of file diff --git a/classes/class.newsletter.logs.php b/classes/class.newsletter.logs.php new file mode 100644 index 0000000..ceeaef9 --- /dev/null +++ b/classes/class.newsletter.logs.php @@ -0,0 +1,243 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01 + * modified 2008-06-30, Dominik Ziegler, add security fix + * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting + * + * $Id: class.newsletter.logs.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +/** + * Collection management class + */ +class cNewsletterLogCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news_log"], "idnewslog"); + $this->_setItemClass("cNewsletterLog"); + } + + /** + * Creates a single new log item + * @param $idnewsjob integer ID of corresponding newsletter send job + * @param $idnewsrcp integer ID of recipient + * @param $rcp_name string Name of the recipient (-> recipient may be deleted) + * @param $rcp_email string E-Mail of the recipient (-> recipient may be deleted) + */ + public function create($idnewsjob, $idnewsrcp) { + global $client, $lang, $auth; + + $idnewsjob = Contenido_Security::toInteger($idnewsjob); + $idnewsrcp = Contenido_Security::toInteger($idnewsrcp); + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + $this->resetQuery(); + $this->setWhere("idnewsjob", $idnewsjob); + $this->setWhere("idnewsrcp", $idnewsrcp); + $this->query(); + + if ($oItem = $this->next()) { + return $oItem; + } + + $oRecipient = new Recipient; + if ($oRecipient->loadByPrimaryKey($idnewsrcp)) { + $oItem = parent::createNewItem(); + + $oItem->set("idnewsjob", $idnewsjob); + $oItem->set("idnewsrcp", $idnewsrcp); + + $sEMail = $oRecipient->get("email"); + $sName = $oRecipient->get("name"); + + if ($sName == "") { + $oItem->set("rcpname", $sEMail); + } else { + $oItem->set("rcpname", $sName); + } + + $oItem->set("rcpemail", $sEMail); + $oItem->set("rcphash", $oRecipient->get("hash")); + $oItem->set("rcpnewstype", $oRecipient->get("news_type")); + $oItem->set("status", "pending"); + $oItem->set("created", date("Y-m-d H:i:s"), false); + $oItem->store(); + + return $oItem; + } else { + return false; + } + } + + /** + * Gets all active recipients as specified for the newsletter and adds for + * every recipient a log item + * @param integer $idnewsjob ID of corresponding newsletter dispatch job + * @param integer $idnews ID of newsletter + * @return integer Recipient count + */ + public function initializeJob($idnewsjob, $idnews) { + global $cfg; + + $idnewsjob = Contenido_Security::toInteger($idnewsjob); + $idnews = Contenido_Security::toInteger($idnews); + + $oNewsletter = new Newsletter(); + if ($oNewsletter->loadByPrimaryKey($idnews)) { + $sDestination = $oNewsletter->get("send_to"); + $iIDClient = $oNewsletter->get("idclient"); + $iIDLang = $oNewsletter->get("idlang"); + + switch ($sDestination) { + case "all" : + $sDistinct = ""; + $sFrom = ""; + $sSQL = "deactivated='0' AND confirmed='1' AND idclient='" . $iIDClient . "' AND idlang='" . $iIDLang . "'"; + break; + case "default" : + $sDistinct = "distinct"; + $sFrom = $cfg["tab"]["news_groups"] . " AS groups, " . $cfg["tab"]["news_groupmembers"] . " AS groupmembers "; + $sSQL = "recipientcollection.idclient = '" . $iIDClient . "' AND " . + "recipientcollection.idlang = '" . $iIDLang . "' AND " . + "recipientcollection.deactivated = '0' AND " . + "recipientcollection.confirmed = '1' AND " . + "recipientcollection.idnewsrcp = groupmembers.idnewsrcp AND " . + "groupmembers.idnewsgroup = groups.idnewsgroup AND " . + "groups.defaultgroup = '1' AND groups.idclient = '" . $iIDClient . "' AND " . + "groups.idlang = '" . $iIDLang . "'"; + break; + case "selection" : + $aGroups = unserialize($oNewsletter->get("send_ids")); + + if (is_array($aGroups) && count($aGroups) > 0) { + $sGroups = "'" . implode("','", $aGroups) . "'"; + + $sDistinct = "distinct"; + $sFrom = $cfg["tab"]["news_groupmembers"] . " AS groupmembers "; + $sSQL = "recipientcollection.idclient = '" . $iIDClient . "' AND " . + "recipientcollection.idlang = '" . $iIDLang . "' AND " . + "recipientcollection.deactivated = '0' AND " . + "recipientcollection.confirmed = '1' AND " . + "recipientcollection.idnewsrcp = groupmembers.idnewsrcp AND " . + "groupmembers.idnewsgroup IN (" . $sGroups . ")"; + } else { + $sDestination = "unknown"; + } + break; + case "single" : + $iID = $oNewsletter->get("send_ids"); + if (is_numeric($iID)) { + $sDistinct = ""; + $sFrom = ""; + $sSQL = "idnewsrcp = '" . $iID . "'"; + } else { + $sDestination = "unknown"; + } + break; + default: + $sDestination = "unknown"; + } + unset($oNewsletter); + + if ($sDestination == "unknown") { + return 0; + } else { + $oRecipients = new RecipientCollection; + $oRecipients->flexSelect($sDistinct, $sFrom, $sSQL, "", "", ""); + + $iRecipients = $oRecipients->count(); + + while ($oRecipient = $oRecipients->next()) { + $this->create($idnewsjob, $oRecipient->get($oRecipient->primaryKey)); + } + + return $iRecipients; + } + } else { + return 0; + } + } + + /** + * Overriden delete function to update recipient count if removing recipient from the list + * @param integer $idnewslog ID + */ + public function delete($idnewslog) { + $idnewslog = Contenido_Security::toInteger($idnewslog); + + $oLog = new cNewsletterLog($idnewslog); + $iIDNewsJob = $oLog->get("idnewsjob"); + unset($oLog); + + $oJob = new cNewsletterJob($iIDNewsJob); + $oJob->set("rcpcount", $oJob->get("rcpcount") - 1); + $oJob->store(); + unset($oJob); + + parent::delete($idnewslog); + } + + public function deleteJob($idnewsjob) { + $idnewsjob = Contenido_Security::toInteger($idnewsjob); + $this->setWhere("idnewsjob", $idnewsjob); + $this->query(); + + while ($oItem = $this->next()) { + $this->delete($oItem->get($oItem->primaryKey)); + } + + return true; + } + +} + +/** + * Single NewsletterLog Item + */ +class cNewsletterLog extends Item { + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news_log"], "idnewslog"); + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + +} diff --git a/classes/class.newsletter.php b/classes/class.newsletter.php new file mode 100644 index 0000000..510011d --- /dev/null +++ b/classes/class.newsletter.php @@ -0,0 +1,998 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01 + * modified 2008-06-30, Dominik Ziegler, add security fix + * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting + * + * $Id: class.newsletter.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +/** + * Newsletter management class + */ +class NewsletterCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news"], "idnews"); + $this->_setItemClass("Newsletter"); + } + + /** + * Creates a new newsletter + * @param $name string specifies the newsletter name + */ + public function create($sName) { + global $client, $lang, $auth; + + $sName = Contenido_Security::escapeDB($sName, null); + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + // Check if the newsletter name already exists + $this->resetQuery; + $this->setWhere("idclient", $client); + $this->setWhere("idlang", $lang); + $this->setWhere("name", $sName); + $this->query(); + + if ($this->next()) { + return $this->create($sName . "_" . substr(md5(rand()), 0, 10)); + } + + $oItem = parent::createNewItem(); + $oItem->set("idclient", $client); + $oItem->set("idlang", $lang); + $oItem->set("name", $sName); + $oItem->set("created", date("Y-m-d H:i:s"), false); + $oItem->set("author", Contenido_Security::escapeDB($auth->auth["uid"], null)); + + $oItem->store(); + + return $oItem; + } + + /** + * Duplicates the newsletter specified by $itemID + * @param $itemID integer specifies the newsletter id + */ + public function duplicate($iItemID) { + global $client, $lang, $auth; + + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + cInclude("includes", "functions.con.php"); + + $oBaseItem = new Newsletter(); + $oBaseItem->loadByPrimaryKey($iItemID); + + $oItem = parent::createNewItem(); + $oItem->set("name", $oBaseItem->get("name") . "_" . substr(md5(rand()), 0, 10)); + + $iIDArt = 0; + if ($oBaseItem->get("type") == "html" && $oBaseItem->get("idart") > 0 && $oBaseItem->get("template_idart") > 0) { + $oClientLang = new cApiClientLanguage(false, $client, $lang); + + if ($oClientLang->getProperty("newsletter", "html_newsletter") == "true") { + $iIDArt = conCopyArticle($oBaseItem->get("idart"), + $oClientLang->getProperty("newsletter", "html_newsletter_idcat"), + sprintf(i18n("Newsletter: %s", "cl_newsletter"), $oItem->get("name"))); + conMakeOnline($iIDArt, $lang); // Article has to be online for sending... + } + unset($oClientLang); + } + $oItem->set("idart", $iIDArt); + $oItem->set("template_idart", $oBaseItem->get("template_idart")); + $oItem->set("idclient", $client); + $oItem->set("idlang", $lang); + $oItem->set("welcome", 0); + $oItem->set("type", $oBaseItem->get("type")); + $oItem->set("subject", $oBaseItem->get("subject")); + $oItem->set("message", $oBaseItem->get("message")); + $oItem->set("newsfrom", $oBaseItem->get("newsfrom")); + $oItem->set("newsfromname", $oBaseItem->get("newsfromname")); + $oItem->set("newsdate", date("Y-m-d H:i:s"), false); // But more or less deprecated + $oItem->set("use_cronjob", $oBaseItem->get("use_cronjob")); + $oItem->set("send_to", $oBaseItem->get("send_to")); + $oItem->set("send_ids", $oBaseItem->get("send_ids")); + $oItem->set("dispatch", $oBaseItem->get("dispatch")); + $oItem->set("dispatch_count", $oBaseItem->get("dispatch_count")); + $oItem->set("dispatch_delay", $oBaseItem->get("dispatch_delay")); + $oItem->set("author", $auth->auth["uid"]); + $oItem->set("created", date("Y-m-d H:i:s"), false); + + // Copy properties, runtime on-demand allocation of the properties object + if (!is_object($this->properties)) { + $this->properties = new PropertyCollection; + } + $this->properties->setWhere("idclient", $client); + $this->properties->setWhere("itemtype", $this->primaryKey); + $this->properties->setWhere("itemid", $iItemID); + $this->properties->query(); + + while ($oPropertyItem = $this->properties->next()) { + $oItem->setProperty($oPropertyItem->get("type"), $oPropertyItem->get("name"), $oPropertyItem->get("value")); + } + + $oItem->store(); + + return $oItem; + } + +} + +/** + * Single Newsletter Item + */ +class Newsletter extends Item { + + /** + * @var string Error storage + * @access private + */ + protected $_sError; + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news"], "idnews"); + $this->_sError = ""; + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + + /** + * Overriden store()-Method to set modified and modifiedby data and + * to ensure, that there is only one welcome newsletter + */ + public function store() { + global $client, $lang, $auth; + + $client = Contenido_Security::toInteger($client); + $lang = Contenido_Security::toInteger($lang); + + $this->set("modified", date("Y-m-d H:i:s"), false); + $this->set("modifiedby", $auth->auth["uid"]); + + if ($this->get("welcome") == 1) { + $oItems = new NewsletterCollection(); + $oItems->setWhere("idclient", $client); + $oItems->setWhere("idlang", $lang); + $oItems->setWhere("welcome", 1); + $oItems->setWhere("idnews", $this->get("idnews"), "<>"); + $oItems->query(); + + while ($oItem = $oItems->next()) { + $oItem->set("welcome", 0); + $oItem->store(); + } + unset($oItem); + unset($oItems); + } + + parent::store(); + } + + /** + * Replaces newsletter tag (e.g. MAIL_NAME) with data. + * If code is just text using str_replace; if it is HTML by using regular expressions + * @param string sCode Code, where the tags will be replaced (by reference) + * @param bool bIsHTML Is code HTML? + * @param string sField Field name, without MAIL_ (e.g. just "name") + * @param string sData Data + * @access private + */ + public function _replaceTag(&$sCode, $bIsHTML, $sField, $sData) { + if ($sCode && !$bIsHTML) { + $sCode = str_replace("MAIL_" . strtoupper($sField), $sData, $sCode); + } else if ($sCode) { + // Extract certain tag + $sRegExp = '/\[mail\s*([^]]+)\s*name=(?:"|")' . $sField . '(?:"|")\s*(.*?)\s*\]((?:.|\s)+?)\[\/mail\]/i'; + $aMatch = array(); + $iMatches = preg_match($sRegExp, $sCode, $aMatch); + + if ($iMatches > 0) { + // $aMatch contains parameter info from left [1] or right [2] to name="field" + $sParameter = $aMatch[1] . $aMatch[2]; + $sMessage = $aMatch[3]; + $sRegExp = '/\s*(.*?)\s*=\s*(?:"|")(.*?)(?:"|")\s*/i'; + $aMatch = array(); + + if (preg_match_all($sRegExp, $sParameter, $aMatch) > 0) { + // Store parameter data as assoziative array + $aParameter = array_combine($aMatch[1], $aMatch[2]); + unset($aMatch); // $aMatch not needed anymore + + if (!array_key_exists("type", $aParameter)) { + $aParameter["type"] = "text"; + } + + switch ($aParameter["type"]) { + case "link": + # TODO: Works everything fine? + # The current code makes it possible to do something like + # [mail ...]Some text here, then the link: [MAIL_STOP] and more text[/mail] + # + # If the other lines will be used, you don't need to + # set [MAIL_xy] and the message between the [mail]-tags will + # be used as link text (instead of using the tag parameter "text") + + $sText = $aParameter["text"]; + + if ($sText == "") { + $sText = $sData; + } + if ($sMessage == "") { + $sMessage = $sData; + } + + // Remove not needed parameters from the parameters list + // everything else goes into the link as parameters + unset($aParameter["type"]); + unset($aParameter["text"]); + + $sParameter = ""; + if (count($aParameter) > 0) { + foreach ($aParameter as $sKey => $sValue) { + $sParameter .= ' ' . $sKey . '="' . $sValue . '"'; + } + } + $sMessage = str_replace("MAIL_" . strtoupper($sField), '' . $sText . '', $sMessage); + #$sMessage = ''.$sMessage.''; + break; + default: + $sMessage = str_replace("MAIL_" . strtoupper($sField), $sData, $sMessage); + #$sMessage = $sData; + } + + $sRegExp = '/\[mail[^]]+name=(?:"|")' . $sField . '(?:"|").*?\].*?\[\/mail\]/is'; + $sCode = preg_replace($sRegExp, $sMessage, $sCode, -1); + // Just to replace "text"-tags in HTML message also, just in case... + $sCode = str_replace("MAIL_" . strtoupper($sField), $sData, $sCode); + } + } + } + } + + /** + * Replaces relative URL for url, src or href with absolute client htmlpath + * + * @author Ortwin Pinke + * @since CL 2.0 + * + * @global int $client + * @global array $cfgClient + * @param string $sUrl + * @return string + */ + protected function _callbackReplaceUrl($sUrl) { + global $client, $cfgClient; + $returnUrl = ''; + print_r($sUrl); + if ($sUrl[1] == "url") { + if (empty($sUrl[3])) { + $returnUrl = $sUrl[1] . "(" . $sUrl[2]; + $returnUrl .= $cfgClient[$client]['path']['htmlpath']; + $returnUrl .= ltrim(ltrim($sUrl[4], "."), "/"); + $returnUrl .= $sUrl[2] . ")"; + } else { + $returnUrl = $sUrl[0]; + } + } else if (empty($sUrl[2])) { + $returnUrl = $sUrl[1] . '="'; + $returnUrl .= $cfgClient[$client]['path']['htmlpath']; + $returnUrl .= ltrim(ltrim($sUrl[3], "."), "/") . '"'; + } else { + $returnUrl = $sUrl[0]; + } + + return $returnUrl; + } + + /* TODO: HerrB: Remove or insert some functionality */ + + protected function _getNewsletterTagData($sHTML, $sTag) { + //$sRegExp = "/](.*?)>.*?<\/newsletter>/i"; + //$sRegExp = "/\[mail[^\]](.*?)>.*?\[\/mail\]/i"; + #\[mail[^\]]((name="(?P.*?)")|(type="(?P.*?)"))\](?P.*?)\[\/mail\] + #\[mail[^\]]((name=(?P[^"]*.*?[^"]*))|(type="(?P.*?)"))\](?P.*?)\[\/mail\] + + /* RegExp explanation: + * Match the character "[" literally �\[� + * Match the characters "mail" literally �mail� + * Match "whitespace characters" (spaces, tabs, line breaks, etc.) after "mail" �\s*� + * Match the regular expression below and capture its match into backreference number 1 �([^]]+)� + * Match any character that is not a "]" �[^]]+� + * Between one and unlimited times, as many times as possible, giving back as needed (greedy) �+� + * Match the character "]" literally �\]� + * Match the regular expression below and capture its match into backreference number 2 �((?:.|\s)+?)� + * Match the regular expression below �(?:.|\s)+?� + * Between one and unlimited times, as few times as possible, expanding as needed (lazy) �+?� + * Match either the regular expression below (attempting the next alternative only if this one fails) �.� + * Match any single character that is not a line break character �.� + * Or match regular expression number 2 below (the entire group fails if this one fails to match) �\s� + * Match a single character that is a "whitespace character" (spaces, tabs, line breaks, etc.) �\s� + * Match the character "[" literally �\[� + * Match the characters "/mail" literally �/mail� + * Match the character "]" literally �\]� + * Ignore case (i), . includes new lines (s) + * */ + + /* + $sRegExp = '/\[mail\s*([^]]+)\]((?:.|\s)+?)\[\/mail\]/is'; + $aMatch = array (); + preg_match_all($sRegExp, $sHTML, $aMatch, PREG_SET_ORDER); + print_r ($aMatch); + + // Auf bestimmten Typ matchen + $sRegExp = '/\[mail.*?name="name".*?\]((?:.|\s)+?)\[\/mail\]/is'; + $aMatch = array (); + preg_match_all($sRegExp, $sHTML, $aMatch, PREG_SET_ORDER); + print_r ($aMatch); */ + + // Parameter auseinandernehmen (ohne PREG_SET_ORDER) + #$sRegExp = '/\s*(.*?)\s*=\s*"(.*?)"\s*/i'; + #$aMatch = array (); + #preg_match_all($sRegExp, $sHTML, $aMatch); + #print_r ($aMatch); + } + + protected function _deChunkHTTPBody($sHeader, $sBody, $sEOL = "\r\n") { + // Based on code from jbr at ya-right dot com, posted on http://www.php.net + // as user comment on fsockopen documentation (2007-05-01) + // Analyze header + $aParts = preg_split("/\r?\n/", $sHeader, -1, PREG_SPLIT_NO_EMPTY); + + $aHeader = array(); + for ($i = 0; $i < sizeof($aParts); $i++) { + if ($i != 0) { + $iPos = strpos($aParts[$i], ':'); + $sParameter = strtolower(str_replace(' ', '', substr($aParts[$i], 0, $iPos))); + $sValue = trim(substr($aParts[$i], ($iPos + 1))); + } else { + $sField = 'status'; + $aParameters = explode(' ', $aParts[$i]); + $sParameter = $aParameters[1]; + } + + if ($sParameter == 'set-cookie') { + $aHeader['cookies'][] = $sValue; + } else if ($sParameter == 'content-type') { + if (($iPos = strpos($sValue, ';')) !== false) { + $aHeader[$sParameter] = substr($sValue, 0, $iPos); + } else { + $aHeader[$sParameter] = $sValue; + } + } else { + $aHeader[$sParameter] = $sValue; + } + } + + // Get dechunked and decompressed body + $iEOLLen = strlen($sEOL); + + $sBuffer = ''; + if (isset($aHeader['transfer-encoding']) && $aHeader['transfer-encoding'] == 'chunked') { + do { + $sBody = ltrim($sBody); + $iPos = strpos($sBody, $sEOL); + $iDataLen = hexdec(substr($sBody, 0, $iPos)); + + if (isset($aHeader['content-encoding'])) { + $sBuffer .= gzinflate(substr($sBody, ($iPos + $iEOLLen + 10), $iDataLen)); + } else { + $sBuffer .= substr($sBody, ($iPos + $iEOLLen), $iDataLen); + } + + $sBody = substr($sBody, ($iPos + $iDataLen + $iEOLLen)); + $sRemaining = trim($sBody); + } while (!empty($sRemaining)); + } else if (isset($aHeader['content-encoding'])) { + $sBuffer = gzinflate(substr($sBody, 10)); + } else { + $sBuffer = $sBody; // Not chunked, not compressed + } + + return $sBuffer; + } + + /** + * If newsletter is HTML newsletter and necessary data available + * returns final HTML message + * @return string HTML message + */ + public function getHTMLMessage() { + global $lang, $client, $cfgClient, $contenido; + + if ($this->get("type") == "html" && $this->get("idart") > 0 && $this->htmlArticleExists()) { + + // Article ID + $iIDArt = $this->get("idart"); + + // Category ID + $oClientLang = new cApiClientLanguage(false, $client, $lang); + $iIDCat = $oClientLang->getProperty("newsletter", "html_newsletter_idcat"); + unset($oClientLang); + + // Get http username and password, if frontend is protected + $oClient = new cApiClient($client); + $sHTTPUserName = $oClient->getProperty("newsletter", "html_username"); + $sHTTPPassword = $oClient->getProperty("newsletter", "html_password"); + unset($oClient); + + // Get HTML + if ($iIDArt > 0 && $iIDCat > 0) { + // Check, if newsletter is online and set temporarely online, otherwise + $bSetOffline = false; + $oArticles = new cApiArticleLanguageCollection; + $oArticles->setWhere("idlang", $this->get("idlang")); + $oArticles->setWhere("idart", $this->get("idart")); + $oArticles->query(); + + if ($oArticle = $oArticles->next()) { + if ($oArticle->get("online") == 0) { + $bSetOffline = true; + $oArticle->set("online", 1); + $oArticle->store(); + } + unset($oArticle); + } + unset($oArticles); + + $sFile = "front_content.php?client=$client&lang=$lang&idcat=$iIDCat&idart=$iIDArt&noex=1&send=1"; + $aURL = parse_url($cfgClient[$client]['path']['htmlpath']); + + // TODO: Other schemes than http should be tested before use! + if ($aURL["scheme"] == "https") { + $iPort = 443; + $sTarget = "ssl://" . $aURL["host"]; + } else { + $iPort = 80; + $sTarget = $aURL["host"]; + } + if ($aURL["port"]) { + $iPort = $aURL["port"]; + } + + $iErrorNo = 0; + $sErrorMsg = ""; + if ($iHandler = fsockopen($sTarget, $iPort, $iErrorNo, $sErrorMsg, 30)) { + // If you use HTTP 1.1 you may get chunked data... you could solve + // this easily by using HTTP 1.0, but then you get a problem with + // virtual servers, as HTTP 1.0 doesn't use the host information... + fputs($iHandler, "GET " . $aURL["path"] . $sFile . " HTTP/1.1\r\n"); + fputs($iHandler, "Host: " . $aURL["host"] . "\r\n"); + + // Maybe the website has been protected using .htaccess, then login + if ($sHTTPUserName != "" && $sHTTPPassword != "") { + fputs($iHandler, "Authorization: Basic " . base64_encode("$sHTTPUserName:$sHTTPPassword") . "\r\n"); + } + + fputs($iHandler, "Referer: http://" . $aURL["host"] . "\r\n"); + fputs($iHandler, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"); + fputs($iHandler, "Connection: close\r\n\r\n"); + + // Get the HTTP header and body separately + $sHTML = ""; + $sHeader = ""; + $bBody = false; + while (!feof($iHandler)) { + // $sLine = fgets($iHandler, 4096); + $sLine = fgets($iHandler, 1024); + if ($bBody) { + $sHTML .= $sLine; + } else if ($sLine == "\r\n") { + $bBody = true; + } else { + $sHeader .= $sLine; + } + } + fclose($iHandler); + + $sHTML = $this->_deChunkHTTPBody($sHeader, $sHTML); + + // If someone likes to use anchors in html newsletters (*sigh*) + // the base href tag has to be removed - that means, we have to fix + // all source paths manually... + if (getEffectiveSetting('newsletter', 'remove_base_tag', "false") == "true") { + // Remove base tag + $sHTML = preg_replace('//is', '', $sHTML, 1); + $sHTML = preg_replace_callback('/(url)\((\'|\")?(http:\/\/|https:\/\/|ftp:\/\/)?([A-Za-z0-9#\.?\-=_&\/]*)[\'|\"]?\)/', array($this, "_callbackReplaceUrl"), $sHTML); + $sHTML = preg_replace_callback('/\b(src|href|ftp)[ ]*=[ ]*"(http:\/\/|https:\/\/|ftp:\/\/)?([A-Za-z0-9#\.?\-=_&\/]*)"/', array($this, "_callbackReplaceUrl"), $sHTML); + // Now replace anchor tags to the newsletter article itself just by the anchor + $sHTML = str_replace($cfgClient[$client]['path']['htmlpath'] . "front_content.php?idart=" . $iIDArt . "#", "#", $sHTML); + } + + $sReturn = $sHTML; + } else { + if ($contenido) { // Use i18n only in backend + $sErrorText = i18n("There was a problem getting the newsletter article using http. Error: %s (%s)", "cl_newsletter"); + } else { + $sErrorText = "There was a problem getting the newsletter article using http. Error: %s (%s)"; + } + + $this->_sError = sprintf($sErrorText, $sErrorMsg, $iErrorNo); + $sReturn = false; + } + + // Set previously offline article back to offline + if ($bSetOffline) { + $oArticles = new cApiArticleLanguageCollection(); + $oArticles->setWhere("idlang", $this->get("idlang")); + $oArticles->setWhere("idart", $this->get("idart")); + $oArticles->query(); + + if ($oArticle = $oArticles->next()) { + $oArticle->set("online", 0); + $oArticle->store(); + } + unset($oArticle); + unset($oArticles); + } + + return $sReturn; + } else { + return false; + } + } else { + return false; + } + } + + /** + * Checks, if html newsletter article still exists + * @return bool + */ + public function htmlArticleExists() { + if ($this->get("idart") > 0) { + $oArticles = new cApiArticleLanguageCollection(); + $oArticles->setWhere("idlang", $this->get("idlang")); + $oArticles->setWhere("idart", $this->get("idart")); + $oArticles->query(); + + if ($oArticles->count() > 0) { + $bReturn = true; + } else { + $bReturn = false; + } + + unset($oArticles); + } else { + $bReturn = false; + } + + return $bReturn; + } + + /** + * Sends test newsletter directly to specified email address + * @param integer $iIDCatArt idcatart of newsletter handler article + * @param string $sEMail Recipient email address + * @param string $sName Optional: Recipient name + * @param bool $bSimulatePlugin If recipient plugin activated, include plugins + * and simulate values from plugins + * @param string $sEncoding Message (and header) encoding, e.g. iso-8859-1 + */ + public function sendEMail($iIDCatArt, $sEMail, $sName = "", $bSimulatePlugins = true, $sEncoding = "iso-8859-1") { + global $lang, $client, $cfg, $cfgClient, $contenido; + + // Initialization + if ($sName == "") { + $sName = $sEMail; + } + + $oLanguage = new cApiLanguage($lang); + $sFormatDate = $oLanguage->getProperty("dateformat", "date"); + $sFormatTime = $oLanguage->getProperty("dateformat", "time"); + unset($oLanguage); + + if ($sFormatDate == "") { + $sFormatDate = "%d.%m.%Y"; + } + if ($sFormatTime == "") { + $sFormatTime = "%H:%M"; + } + + // Get newsletter data + $sFrom = $this->get("newsfrom"); + $sFromName = $this->get("newsfromname"); + if ($sFromName == "") { + $sFromName = $sFrom; + } + $sSubject = $this->get("subject"); + $sMessageText = $this->get("message"); + + $bIsHTML = false; + if ($this->get("type") == "html") { + $sMessageHTML = $this->getHTMLMessage(); + + if ($sMessageHTML === false) { + // There was a problem getting the html message (maybe article + // deleted). Exit with error instead of sending as text message only + + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent: No html message available", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent: No html message available"; + } + $this->_sError = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + return false; + } else { + $bIsHTML = true; + } + } + + // Preventing double lines in mail, you may wish to disable this function on windows servers + if (!getSystemProperty("newsletter", "disable-rn-replacement")) { + $sMessageText = str_replace("\r\n", "\n", $sMessageText); + } + + // Simulate key, an alphanumeric string of 30 characters + $sKey = str_repeat("key", 10); + $sPath = $cfgClient[$client]["path"]["htmlpath"] . "front_content.php?changelang=" . $lang . "&idcatart=" . $iIDCatArt . "&"; + + // Replace message tags (text message) + $this->_replaceTag($sMessageText, false, "name", $sName); + $this->_replaceTag($sMessageText, false, "number", 1); + $this->_replaceTag($sMessageText, false, "date", strftime($sFormatDate)); + $this->_replaceTag($sMessageText, false, "time", strftime($sFormatTime)); + $this->_replaceTag($sMessageText, false, "unsubscribe", $sPath . "unsubscribe=" . $sKey); + $this->_replaceTag($sMessageText, false, "change", $sPath . "change=" . $sKey); + $this->_replaceTag($sMessageText, false, "stop", $sPath . "stop=" . $sKey); + $this->_replaceTag($sMessageText, false, "goon", $sPath . "goon=" . $sKey); + + // Replace message tags (html message) + if ($bIsHTML) { + $this->_replaceTag($sMessageHTML, true, "name", $sName); + $this->_replaceTag($sMessageHTML, true, "number", 1); + $this->_replaceTag($sMessageHTML, true, "date", strftime($sFormatDate)); + $this->_replaceTag($sMessageHTML, true, "time", strftime($sFormatTime)); + $this->_replaceTag($sMessageHTML, true, "unsubscribe", $sPath . "unsubscribe=" . $sKey); + $this->_replaceTag($sMessageHTML, true, "change", $sPath . "change=" . $sKey); + $this->_replaceTag($sMessageHTML, true, "stop", $sPath . "stop=" . $sKey); + $this->_replaceTag($sMessageHTML, true, "goon", $sPath . "goon=" . $sKey); + } + + if ($bSimulatePlugins) { + // Enabling plugin interface + if (getSystemProperty("newsletter", "newsletter-recipients-plugin") == "true") { + if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $sPlugin) { + plugin_include("recipients", $sPlugin . "/" . $sPlugin . ".php"); + if (function_exists("recipients_" . $sPlugin . "_wantedVariables")) { + $aPluginVars = array(); + $aPluginVars = call_user_func("recipients_" . $sPlugin . "_wantedVariables"); + + foreach ($aPluginVars as $sPluginVar) { + // Replace tags in text message + $this->_replaceTag($sMessageText, false, $sPluginVar, ":: " . $sPlugin . ": " . $sPluginVar . " ::"); + // Replace tags in html message + if ($bIsHTML) { + $this->_replaceTag($sMessageHTML, true, $sPluginVar, ":: " . $sPlugin . ": " . $sPluginVar . " ::"); + } + } + } + } + } + } else { + setSystemProperty("newsletter", "newsletter-recipients-plugin", "false"); + } + } + + if (!isValidMail($sEMail) || strtolower($sEMail) == "sysadmin@ihresite.de") { + // No valid destination mail address specified + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent: No valid e-mail address", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent: No valid e-mail address"; + } + $this->_sError = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + return false; + } else { + $oMail = new PHPMailer(); + $oMail->CharSet = $sEncoding; + $oMail->IsHTML($bIsHTML); + $oMail->From = $sFrom; + $oMail->FromName = $sFromName; + $oMail->AddAddress($sEMail); + $oMail->Mailer = "mail"; + $oMail->Subject = $sSubject; + + if ($bIsHTML) { + $oMail->Body = $sMessageHTML; + $oMail->AltBody = $sMessageText . "\n\n"; + } else { + $oMail->Body = $sMessageText . "\n\n"; + } + + if (!$oMail->Send()) { + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent"; + } + $this->_sError = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + return false; + } else { + return true; + } + } + } + + /** + * Sends test newsletter directly to specified recipients (single or group) + * + * Note: Sending in chunks not supported! Only usable for tests and only a few + * recipients. + * + * @param integer $iIDCatArt idcatart of newsletter handler article + * @param integer $iIDNewsRcp If specified, newsletter recipient id, ignored, if group specified + * @param integer $iIDNewsGroup If specified, newsletter recipient group id + * @param array $aSendRcps As reference: Filled with a list of succesfull recipients + * @param string $sEncoding Message (and header) encoding, e.g. iso-8859-1 + */ + public function sendDirect($iIDCatArt, $iIDNewsRcp = false, $iIDNewsGroup = false, &$aSendRcps, $sEncoding = "iso-8859-1") { + global $lang, $client, $cfg, $cfgClient, $contenido, $recipient; + + // Initialization + $aMessages = array(); + + $oLanguage = new cApiLanguage($lang); + $sFormatDate = $oLanguage->getProperty("dateformat", "date"); + $sFormatTime = $oLanguage->getProperty("dateformat", "time"); + unset($oLanguage); + + if ($sFormatDate == "") { + $sFormatDate = "%d.%m.%Y"; + } + if ($sFormatTime == "") { + $sFormatTime = "%H:%M"; + } + + $sPath = $cfgClient[$client]["path"]["htmlpath"] . "front_content.php?changelang=" . $lang . "&idcatart=" . $iIDCatArt . "&"; + + // Get newsletter data + $sFrom = $this->get("newsfrom"); + $sFromName = $this->get("newsfromname"); + if ($sFromName == "") { + $sFromName = $sFrom; + } + $sSubject = $this->get("subject"); + $sMessageText = $this->get("message"); + + $bIsHTML = false; + if ($this->get("type") == "html") { + $sMessageHTML = $this->getHTMLMessage(); + + if ($sMessageHTML === false) { + // There was a problem getting the html message (maybe article + // deleted). Exit with error instead of sending as text message only + + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter could not be sent: No html message available", "cl_newsletter"); + } else { + $sError = "Newsletter could not be sent: No html message available"; + } + $this->_sError = $sError; + return false; + } else { + $bIsHTML = true; + } + } + + // Preventing double lines in mail, you may wish to disable this function on windows servers + if (!getSystemProperty("newsletter", "disable-rn-replacement")) { + $sMessageText = str_replace("\r\n", "\n", $sMessageText); + } + + // Single replacements + // Replace message tags (text message) + $this->_replaceTag($sMessageText, false, "date", strftime($sFormatDate)); + $this->_replaceTag($sMessageText, false, "time", strftime($sFormatTime)); + + // Replace message tags (html message) + if ($bIsHTML) { + $this->_replaceTag($sMessageHTML, true, "date", strftime($sFormatDate)); + $this->_replaceTag($sMessageHTML, true, "time", strftime($sFormatTime)); + } + + // Enabling plugin interface + if (getSystemProperty("newsletter", "newsletter-recipients-plugin") == "true") { + $bPluginEnabled = true; + $aPlugins = array(); + + if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $sPlugin) { + plugin_include("recipients", $sPlugin . "/" . $sPlugin . ".php"); + if (function_exists("recipients_" . $sPlugin . "_wantedVariables")) { + $aPlugins[$sPlugin] = call_user_func("recipients_" . $sPlugin . "_wantedVariables"); + } + } + } + } else { + setSystemProperty("newsletter", "newsletter-recipients-plugin", "false"); + $bPluginEnabled = false; + } + + $aRecipients = array(); + if ($iIDNewsGroup !== false) { + $oGroupMembers = new RecipientGroupMemberCollection; + $aRecipients = $oGroupMembers->getRecipientsInGroup($iIDNewsGroup, false); + } else if ($iIDNewsRcp !== false) { + $aRecipients[] = $iIDNewsRcp; + } + + $iCount = count($aRecipients); + if ($iCount > 0) { + $this->_replaceTag($sMessageText, false, "number", $iCount); + + // Replace message tags (html message) + if ($bIsHTML) { + $this->_replaceTag($sMessageHTML, true, "number", $iCount); + } + + foreach ($aRecipients as $iID) { + $sRcpMsgText = $sMessageText; + $sRcpMsgHTML = $sMessageHTML; + + // Don't change name of $recipient variable as it is used in plugins! + $recipient = new Recipient; + $recipient->loadByPrimaryKey($iID); + + $sEMail = $recipient->get("email"); + $sName = $recipient->get("name"); + if (empty($sName)) { + $sName = $sEMail; + } + $sKey = $recipient->get("hash"); + + $bSendHTML = false; + if ($recipient->get("news_type") == 1) { + $bSendHTML = true; // Recipient accepts html newsletter + } + + $this->_replaceTag($sRcpMsgText, false, "name", $sName); + $this->_replaceTag($sRcpMsgText, false, "unsubscribe", $sPath . "unsubscribe=" . $sKey); + $this->_replaceTag($sRcpMsgText, false, "change", $sPath . "change=" . $sKey); + $this->_replaceTag($sRcpMsgText, false, "stop", $sPath . "stop=" . $sKey); + $this->_replaceTag($sRcpMsgText, false, "goon", $sPath . "goon=" . $sKey); + + // Replace message tags (html message) + if ($bIsHTML && $bSendHTML) { + $this->_replaceTag($sRcpMsgHTML, true, "name", $sName); + $this->_replaceTag($sRcpMsgHTML, true, "unsubscribe", $sPath . "unsubscribe=" . $sKey); + $this->_replaceTag($sRcpMsgHTML, true, "change", $sPath . "change=" . $sKey); + $this->_replaceTag($sRcpMsgHTML, true, "stop", $sPath . "stop=" . $sKey); + $this->_replaceTag($sRcpMsgHTML, true, "goon", $sPath . "goon=" . $sKey); + } + + if ($bPluginEnabled) { + foreach ($aPlugins as $sPlugin => $aPluginVar) { + foreach ($aPluginVar as $sPluginVar) { + // Replace tags in text message + $this->_replaceTag($sRcpMsgText, false, $sPluginVar, call_user_func("recipients_" . $sPlugin . "_getvalue", $sPluginVar)); + // Replace tags in html message + if ($bIsHTML && $bSendHTML) { + $this->_replaceTag($sRcpMsgHTML, true, $sPluginVar, call_user_func("recipients_" . $sPlugin . "_getvalue", $sPluginVar)); + } + } + } + } + + if (strlen($sKey) != 30) { // Prevents sending without having a key + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent: Recipient has an incompatible or empty key", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent: Recipient has an incompatible or empty key"; + } + $aMessages[] = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + } else if (!isValidMail($sEMail)) { + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent: No valid e-mail address specified", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent: No valid e-mail address specified"; + } + $aMessages[] = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + } else { + $oMail = new PHPMailer(); + $oMail->CharSet = $sEncoding; + $oMail->IsHTML($bIsHTML && $bSendHTML); + $oMail->From = $sFrom; + $oMail->FromName = $sFromName; + $oMail->AddAddress($sEMail); + $oMail->Mailer = "mail"; + $oMail->Subject = $sSubject; + + if ($bIsHTML && $bSendHTML) { + $oMail->Body = $sRcpMsgHTML; + $oMail->AltBody = $sRcpMsgText . "\n\n"; + } else { + $oMail->Body = $sRcpMsgText . "\n\n"; + } + + if ($oMail->Send()) { + $aSendRcps[] = $sName . " (" . $sEMail . ")"; + } else { + if ($contenido) { // Use i18n only in backend + $sError = i18n("Newsletter to %s could not be sent", "cl_newsletter"); + } else { + $sError = "Newsletter to %s could not be sent"; + } + $aMessages[] = $sName . " (" . $sEMail . "): " . sprintf($sError, $sEMail); + } + } + } + } else { + if ($contenido) { // Use i18n only in backend + $sError = i18n("No recipient with specified recipient/group id %s/%s found", "cl_newsletter"); + } else { + $sError = "No recipient with specified recpient/group id %s/%s found"; + } + $aMessages[] = sprintf($sError, $iIDNewsRcp, $iIDNewsGroup); + } + + if (count($aMessages) > 0) { + $this->_sError = implode("
", $aMessages); + return false; + } else { + return true; + } + } + + /** + * @deprecated >V4.6.15 - 21.05.2007 + * + * Sends a newsletter + * @param $idcatart integer specifies id of the 'BlackBox'-acrticle containing the 'BlackBox'-module for management + * @param $destination string specifies, who will receive the newsletter ("all", "default" = defaultgroup, + * "selection" = selected groups, "single" = one recepient [e.g. Welcome-Newsletter]) + * @param $to array specifies, which group of recipients shall receive the + * newsletter ("all", "default" = defaultgroup, "4,5,6" = group IDs) + * @param $iChunkSize integer specifies size of chunks when sending in chunks, 0 = don't send in chunks + * @param $iChunk integer specifies current chunk number when sending in chunks + * result array array of recipient names/e-mails + */ + public function send($idcatart, $destination = "other", $to = "", $iChunkSize = 0, $iChunk = 0, $sEncoding = "iso-8859-1") { + // What should we do with this deprecated method? + $aResult = array(); + $aResult[] = 0; + $aResult[] = "Newsletter->send() not supported anymore (class.newsletter.php)"; + return $aResult; + } + +} diff --git a/classes/class.newsletter.recipients.php b/classes/class.newsletter.recipients.php new file mode 100644 index 0000000..c7c9561 --- /dev/null +++ b/classes/class.newsletter.recipients.php @@ -0,0 +1,248 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01 + * modified 2008-06-30, Dominik Ziegler, add security fix + * modified 2011-03-14, Murat Purc, adapted to new GenericDB, partly ported to PHP 5, formatting + * + * $Id: class.newsletter.recipients.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +/** + * Recipient management class + */ +class RecipientCollection extends ItemCollection { + + /** + * Constructor Function + * @param none + */ + public function __construct() { + global $cfg; + parent::__construct($cfg["tab"]["news_rcp"], "idnewsrcp"); + $this->_setItemClass("Recipient"); + } + + /** + * Creates a new recipient + * @param string $sEMail Specifies the e-mail adress + * @param string $sName Specifies the recipient name (optional) + * @param int $iConfirmed Specifies, if the recipient is confirmed (optional) + * @param string $sJoinID Specifies additional recipient group ids to join (optional, e.g. 47,12,...) + * @param int $iMessageType Specifies the message type for the recipient (0 = text, 1 = html) + */ + public function create($sEMail, $sName = "", $iConfirmed = 0, $sJoinID = "", $iMessageType = 0) { + global $client, $lang, $auth; + + $iConfirmed = (int) $iConfirmed; + $iMessageType = (int) $iMessageType; + + /* Check if the e-mail adress already exists */ + $email = strtolower($email); // e-mail always lower case + $this->setWhere("idclient", $client); + $this->setWhere("idlang", $lang); + $this->setWhere("email", $sEMail); + $this->query(); + + if ($this->next()) { + return $this->create($sEMail . "_" . substr(md5(rand()), 0, 10), $sName, 0, $sJoinID, $iMessageType); // 0: Deactivate 'confirmed' + } + $oItem = parent::createNewItem(); + $oItem->set("idclient", $client); + $oItem->set("idlang", $lang); + $oItem->set("name", $sName); + $oItem->set("email", $sEMail); + $oItem->set("hash", substr(md5(rand()), 0, 17) . uniqid("")); // Generating UID, 30 characters + $oItem->set("confirmed", $iConfirmed); + $oItem->set("news_type", $iMessageType); + + if ($iConfirmed) { + $oItem->set("confirmeddate", date("Y-m-d H:i:s"), false); + } + $oItem->set("deactivated", 0); + $oItem->set("created", date("Y-m-d H:i:s"), false); + $oItem->set("author", $auth->auth["uid"]); + $oItem->store(); + + $iIDRcp = $oItem->get("idnewsrcp"); // Getting internal id of new recipient + // Add this recipient to the default recipient group (if available) + $oGroups = new RecipientGroupCollection(); + $oGroupMembers = new RecipientGroupMemberCollection(); + + $oGroups->setWhere("idclient", $client); + $oGroups->setWhere("idlang", $lang); + $oGroups->setWhere("defaultgroup", 1); + $oGroups->query(); + + while ($oGroup = $oGroups->next()) { + $iIDGroup = $oGroup->get("idnewsgroup"); + $oGroupMembers->create($iIDGroup, $iIDRcp); + } + + // Add to other recipient groups as well? Do so! + if ($sJoinID != "") { + $aJoinID = explode(",", $sJoinID); + + if (count($aJoinID) > 0) { + foreach ($aJoinID as $iIDGroup) { + $oGroupMembers->create($iIDGroup, $iIDRcp); + } + } + } + + return $oItem; + } + + /** + * Overridden delete method to remove recipient from groupmember table + * before deleting recipient + * + * @param $itemID int specifies the recipient + */ + public function delete($itemID) { + $oAssociations = new RecipientGroupMemberCollection(); + $oAssociations->setWhere("idnewsrcp", $itemID); + $oAssociations->query(); + + While ($oItem = $oAssociations->next()) { + $oAssociations->delete($oItem->get("idnewsgroupmember")); + } + parent::delete($itemID); + } + + /** + * Purge method to delete recipients which hasn't been confirmed since over a month + * @param $timeframe int Days after creation a not confirmed recipient will be removed + * @return int Count of deleted recipients + */ + public function purge($timeframe) { + global $client, $lang; + + $oRecipientCollection = new RecipientCollection(); + + // DATEDIFF(created, NOW()) > 30 would be better, but it's only available in MySQL V4.1.1 and above + // Note, that, TO_DAYS or NOW may not be available in other database systems than MySQL + $oRecipientCollection->setWhere("idclient", $client); + $oRecipientCollection->setWhere("idlang", $lang); + $oRecipientCollection->setWhere("confirmed", 0); + $oRecipientCollection->setWhere("(TO_DAYS(NOW()) - TO_DAYS(created))", $timeframe, ">"); + $oRecipientCollection->query(); + + while ($oItem = $oRecipientCollection->next()) { + $oRecipientCollection->delete($oItem->get("idnewsrcp")); + } + return $oRecipientCollection->count(); + } + + /** + * checkEMail returns true, if there is no recipient with the same e-mail address; otherwise false + * @param $email string e-mail + * @return recpient item if item with e-mail exists, false otherwise + */ + public function emailExists($sEmail) { + global $client, $lang; + + $oRecipientCollection = new RecipientCollection(); + + $oRecipientCollection->setWhere("idclient", $client); + $oRecipientCollection->setWhere("idlang", $lang); + $oRecipientCollection->setWhere("email", strtolower($sEmail)); + $oRecipientCollection->query(); + + if ($oItem = $oRecipientCollection->next()) { + return $oItem; + } else { + return false; + } + } + + /** + * Sets a key for all recipients without key or an old key (len(key) <> 30) + * @param none + */ + public function updateKeys() { + $this->setWhere("LENGTH(hash)", 30, "<>"); + $this->query(); + + $iUpdated = $this->count(); + while ($oItem = $this->next()) { + $oItem->set("hash", substr(md5(rand()), 0, 17) . uniqid("")); /* Generating UID, 30 characters */ + $oItem->store(); + } + + return $iUpdated; + } + +} + +/** + * Single Recipient Item + */ +class Recipient extends Item { + + /** + * Constructor Function + * @param mixed $mId Specifies the ID of item to load + */ + public function __construct($mId = false) { + global $cfg; + parent::__construct($cfg["tab"]["news_rcp"], "idnewsrcp"); + if ($mId !== false) { + $this->loadByPrimaryKey($mId); + } + } + + public function store() { + global $auth; + + $this->set("lastmodified", date("Y-m-d H:i:s"), false); + $this->set("modifiedby", $auth->auth["uid"]); + parent::store(); + + // Update name, email and newsletter type for recipients in pending newsletter jobs + $sName = $this->get("name"); + $sEmail = $this->get("email"); + if ($sName == "") { + $sName = $sEmail; + } + $iNewsType = $this->get("news_type"); + + $oLogs = new cNewsletterLogCollection(); + $oLogs->setWhere("idnewsrcp", $this->get($this->primaryKey)); + $oLogs->setWhere("status", "pending"); + $oLogs->query(); + + while ($oLog = $oLogs->next()) { + $oLog->set("rcpname", $sName); + $oLog->set("rcpemail", $sEmail); + $oLog->set("rcpnewstype", $iNewsType); + $oLog->store(); + } + } + +} diff --git a/includes/config.autoloader.php b/includes/config.autoloader.php new file mode 100644 index 0000000..ee797c9 --- /dev/null +++ b/includes/config.autoloader.php @@ -0,0 +1,17 @@ + $sAutoloadClassPath.'class.newsletter.groups.php', + 'RecipientGroup' => $sAutoloadClassPath.'class.newsletter.groups.php', + 'RecipientGroupMemberCollection' => $sAutoloadClassPath.'class.newsletter.groups.php', + 'RecipientGroupMember' => $sAutoloadClassPath.'class.newsletter.groups.php', + 'cNewsletterJobCollection' => $sAutoloadClassPath.'class.newsletter.jobs.php', + 'cNewsletterJob' => $sAutoloadClassPath.'class.newsletter.jobs.php', + 'cNewsletterLogCollection' => $sAutoloadClassPath.'class.newsletter.logs.php', + 'cNewsletterLog' => $sAutoloadClassPath.'class.newsletter.logs.php', + 'NewsletterCollection' => $sAutoloadClassPath.'class.newsletter.php', + 'Newsletter' => $sAutoloadClassPath.'class.newsletter.php', + 'RecipientCollection' => $sAutoloadClassPath.'class.newsletter.recipients.php', + 'Recipient' => $sAutoloadClassPath.'class.newsletter.recipients.php' +); +?> \ No newline at end of file diff --git a/includes/config.plugin.php b/includes/config.plugin.php new file mode 100644 index 0000000..2af7a61 --- /dev/null +++ b/includes/config.plugin.php @@ -0,0 +1,35 @@ + + * @copyright 2012 CL-Team + * @link http://www.conlite.org + * + * $Id: config.plugin.php 128 2019-07-03 11:58:28Z oldperl $ + */ + +// security check +defined('CON_FRAMEWORK') or die('Illegal call'); + +class nlHandler extends pluginHandlerAbstract { + +} + +/* +plugin_include(nlHandler::getName(), "includes/functions/demo1.php"); +plugin_include(nlHandler::getName(), "includes/functions/demo2.php"); + */ + + +$cfg["tab"]["news"] = $cfg['sql']['sqlprefix']."_pi_news"; +$cfg["tab"]["news_rcp"] = $cfg['sql']['sqlprefix']."_pi_news_rcp"; +$cfg["tab"]["news_groups"] = $cfg['sql']['sqlprefix']."_pi_news_groups"; +$cfg["tab"]["news_groupmembers"] = $cfg['sql']['sqlprefix']."_pi_news_groupmembers"; +$cfg["tab"]["news_jobs"] = $cfg['sql']['sqlprefix']."_pi_news_jobs"; +$cfg["tab"]["news_log"] = $cfg['sql']['sqlprefix']."_pi_news_log"; \ No newline at end of file diff --git a/includes/include.newsletter_edit.php b/includes/include.newsletter_edit.php new file mode 100644 index 0000000..fc6d9d8 --- /dev/null +++ b/includes/include.newsletter_edit.php @@ -0,0 +1,556 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * modified 2010-12-14, Dominik Ziegler, newsletter encoding is ignored due to wrong parameter values [#CON-374] + * + * $Id: include.newsletter_edit.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +// Initialization +$oPage = new cPage(); +$oRcpGroups = new RecipientGroupCollection(); +$oClientLang = new cApiClientLanguage(false, $client, $lang); +$oNewsletters = new NewsletterCollection(); + +// Include plugins +if (is_array($cfg['plugins']['newsletters'])) { + foreach ($cfg['plugins']['newsletters'] as $plugin) { + plugin_include("newsletters", $plugin . "/" . $plugin . ".php"); + } +} + +if ($action == "news_create" && $perm->have_perm_area_action($area, "news_create")) { + // Create new newsletter + $oNewsletter = $oNewsletters->create(i18n("-- new newsletter --", "cl_newsletter")); + $idnewsletter = $oNewsletter->get("idnews"); + $oPage->setSubnav("idnewsletter=$idnewsletter", "news"); + $oPage->setReload(); + + // Populating default values + $oNewsletter->set("newsfrom", $oClientLang->getProperty("newsletter", "newsfrom")); + $oNewsletter->set("newsfromname", $oClientLang->getProperty("newsletter", "newsfromname")); + + $sValue = $oClientLang->getProperty("newsletter", "sendto"); + if ($sValue == "") { + $sValue = "all"; + } + $oNewsletter->set("send_to", $sValue); + + $oNewsletter->set("send_ids", $oClientLang->getProperty("newsletter", "sendids")); + + $iValue = $oClientLang->getProperty("newsletter", "use_cronjob"); + if (!is_numeric($iValue)) { + $iValue = 0; + } + $oNewsletter->set("use_cronjob", $iValue); + + $iValue = $oClientLang->getProperty("newsletter", "dispatch"); + if (!is_numeric($iValue)) { + $iValue = 0; + } + $oNewsletter->set("dispatch", $iValue); + + $iValue = $oClientLang->getProperty("newsletter", "dispatchcount"); + if (!is_numeric($iValue)) { + $iValue = 50; + } + $oNewsletter->set("dispatch_count", $iValue); + + $iValue = $oClientLang->getProperty("newsletter", "dispatchdelay"); + if (!is_numeric($iValue)) { + $iValue = 5; + } + $oNewsletter->set("dispatch_delay", $iValue); + $oNewsletter->store(); +} else if ($action == "news_duplicate" && $perm->have_perm_area_action($area, "news_create")) { + // Copy newsletter + $oNewsletter = $oNewsletters->duplicate($idnewsletter); + + // Update subnav with new ID + $oPage->setSubnav("idnewsletter=" . $oNewsletter->get("idnews"), "news"); + $oPage->setReload(); +} else if ($action == "news_delete" && $perm->have_perm_area_action($area, "news_delete")) { + // Delete newsletter + // If it is an html newsletter, delete html message article, also + $oNewsletter = new Newsletter($idnewsletter); + + if ($oNewsletter->get("type") == "html" && $oNewsletter->get("idart") > 0) { + conDeleteArt($oNewsletter->get("idart")); + } + + // Delete newsletter + $oNewsletters->delete($idnewsletter); + $oNewsletter = new Newsletter; // Generate empty newsletter object + // Setting blank subnav - "blank" doesn't mean anything special, it just can't be empty + // and must not contain "idnewsletter" as this is checked in the _subnav file. + $oPage->setSubnav("blank", "news"); + $oPage->setReload(); +} else if ($action == "news_add_job" && $perm->have_perm_area_action($area, "news_add_job")) { + // Create job + $oJobs = new cNewsletterJobCollection; + $oJob = $oJobs->create($idnewsletter, $oClientLang->getProperty("newsletter", "idcatart")); + unset($oJobs); + + if ($oJob) { + $notis = $notification->returnNotification("info", i18n("Newsletter dispatch job has been added for this newsletter", "cl_newsletter")) . "
"; + } else { + $notis = $notification->returnNotification("error", i18n("Newsletter dispatch job has been not been added! Please check newsletter details", "cl_newsletter")) . "
"; + } + + $oNewsletter = new Newsletter($idnewsletter); +} else if ($action == "news_send_test" && + ($perm->have_perm_area_action($area, "news_create") || + $perm->have_perm_area_action($area, "news_save") || + $perm->have_perm_area_action($area, "news_add_job"))) { + // Send test newsletter + $oUser = new cApiUser($auth->auth["uid"]); + + // Subnav gets not updated otherwise (no multilink from newsletter_menu) + $oPage->setSubnav("idnewsletter=" . $idnewsletter, "news"); + + // Get test destination + if ($perm->have_perm_area_action($area, "news_send_test")) { + $iTestIDNewsGroup = (int) $oUser->getProperty("newsletter", "test_idnewsgrp_lang" . $lang); + } else { + $iTestIDNewsGroup = 0; // If user doesn't have the news_send_test right, just send to himself + } + + // Get encoding + $oLang = new cApiLanguage($lang); + $sEncoding = $oLang->get("encoding"); + unset($oLang); + + // Send test newsletter + $oNewsletter = new Newsletter($idnewsletter); + $aRecipients = array(); + if ($iTestIDNewsGroup == 0) { + // Send test newsletter to current user email address + $sName = $oUser->get("realname"); + $sEMail = $oUser->get("email"); + + $bSend = $oNewsletter->sendEMail($oClientLang->getProperty("newsletter", "idcatart"), $sEMail, $sName, true, $sEncoding); + if ($bSend) { + $aRecipients[] = $sName . " (" . $sEMail . ")"; + } else { + $aRecipients[] = i18n("None", "cl_newsletter"); + } + } else { + $bSend = $oNewsletter->sendDirect($oClientLang->getProperty("newsletter", "idcatart"), 0, $iTestIDNewsGroup, $aRecipients, $sEncoding); + } + unset($oUser); + + if ($bSend) { + $notis = $notification->returnNotification("info", i18n("Test newsletter has been sent to:", "cl_newsletter") . "
" . implode("
", $aRecipients) . "
"); + } else { + $notis = $notification->returnNotification("warning", i18n("Test newsletter has not been sent (partly or completely):", "cl_newsletter") . "
" . + i18n("Successful:", "cl_newsletter") . "
" . implode("
", $aRecipients) . "
" . + i18n("Error messages:", "cl_newsletter") . "
" . $oNewsletter->_sError); + } +} else { + // No action, just get selected newsletter + $oNewsletter = new Newsletter($idnewsletter); +} + +if ($oNewsletter->virgin == false && $oNewsletter->get("idclient") == $client && $oNewsletter->get("idlang") == $lang) { + // Check and set values + if ($_REQUEST["optSendTo"] == "") { + $_REQUEST["optSendTo"] = $oNewsletter->get("send_to"); + } + + if (!is_numeric($_REQUEST["ckbWelcome"])) { + $_REQUEST["ckbWelcome"] = 0; + } + + if (!is_numeric($_REQUEST["txtDispatchCount"]) || $_REQUEST["txtDispatchCount"] <= 0) { + $_REQUEST["txtDispatchCount"] = $oNewsletter->get("dispatch_count"); + } + + // Note, that for DispatchDelay 0 is possible (= send chunks manually) + if (!is_numeric($_REQUEST["txtDispatchDelay"]) || $_REQUEST["txtDispatchDelay"] < 0) { + $_REQUEST["txtDispatchDelay"] = $oNewsletter->get("dispatch_delay"); + } + + // Only set template id to 0 if it has been specified (as something not useful). + // This prevents deleting of the template id, if type setting is changed to "text" + if (isset($_REQUEST["selTemplate"]) && !is_numeric($_REQUEST["selTemplate"])) { + $_REQUEST["selTemplate"] = 0; + } + + if ($action == "news_save" && $perm->have_perm_area_action($area, $action)) { + // Save changes + $aMessages = array(); + + // Changing e.g. \' back to ' (magic_quotes) + $sName = stripslashes($_REQUEST["txtName"]); + $sFromEMail = stripslashes($_REQUEST["txtFromEMail"]); + $sFromName = stripslashes($_REQUEST["txtFromName"]); + $sSubject = stripslashes($_REQUEST["txtSubject"]); + + if ($oNewsletter->get("name") != $sName || + $oNewsletter->get("welcome") != $_REQUEST["ckbWelcome"] || + !isValidMail($oNewsletter->get("newsfrom")) && isValidMail($sFromEMail)) { + // Only reload, if something visible has changed + $oPage->setReload(); + } + + if ($oNewsletter->get("name") != $sName) { + // Check, if item with same name exists + $oNewsletters->setWhere("name", $sName); + $oNewsletters->setWhere("idclient", $client); + $oNewsletters->setWhere("idlang", $lang); + $oNewsletters->setWhere($oNewsletter->primaryKey, $oNewsletter->get($oNewsletter->primaryKey), "!="); + $oNewsletters->query(); + + if ($oNewsletters->next()) { + $aMessages[] = i18n("Could not set new newsletter name: name already exists", "cl_newsletter"); + } else { + $oNewsletter->set("name", $sName); + if ($oNewsletter->get("idart") > 0) { + // Update also HTML newsletter article title, if newsletter name has been changed + $oArticles = new cApiArticleLanguageCollection; + $oArticles->setWhere("idlang", $lang); + $oArticles->setWhere("idart", $oNewsletter->get("idart")); + $oArticles->query(); + + if ($oArticle = $oArticles->next()) { + $oArticle->set("title", sprintf(i18n("Newsletter: %s", "cl_newsletter"), $oNewsletter->get("name"))); + $oArticle->store(); + } + unset($oArticle); + unset($oArticles); + } + } + } + if ($oClientLang->getProperty("newsletter", "html_newsletter") == "true") { + $oNewsletter->set("type", $selType); + } else { + $oNewsletter->set("type", "text"); + } + $oNewsletter->set("newsfrom", $sFromEMail); + $oNewsletter->set("newsfromname", $sFromName); + $oNewsletter->set("subject", $sSubject); + + // Options + $oNewsletter->set("welcome", $_REQUEST["ckbWelcome"]); + + // Check out if there are any plugins + if (is_array($cfg['plugins']['newsletters'])) { + foreach ($cfg['plugins']['newsletters'] as $plugin) { + if (function_exists("newsletters_" . $plugin . "_wantedVariables") && function_exists("newsletters_" . $plugin . "_store")) { + $wantVariables = call_user_func("newsletters_" . $plugin . "_wantedVariables"); + + if (is_array($wantVariables)) { + $varArray = array(); + + foreach ($wantVariables as $value) { + $varArray[$value] = stripslashes($GLOBALS[$value]); + } + } + $store = call_user_func("newsletters_" . $plugin . "_store", $varArray); + } + } + } + + // If "selected groups" have been selected and no group specified, set + // selection to "all" + if ($_REQUEST["optSendTo"] == "selection" && !is_array($_REQUEST["selGroup"])) { + $aMessages[] = i18n("'Send to recipients in selected groups' has been selected, but no group has been specified. Selection has been set to 'Send to all recipients'", "cl_newsletter"); + $_REQUEST["optSendTo"] = "all"; + } + $oNewsletter->set("send_to", $_REQUEST["optSendTo"]); + $oNewsletter->set("send_ids", serialize($_REQUEST["selGroup"])); + + if (getEffectiveSetting("newsletter", "option-cronjob-available", "false") == "true") { + // Only store changes, if cronjob option is available + if (isset($_REQUEST["ckbCronJob"])) { + $oNewsletter->set("use_cronjob", 1); + } else { + $oNewsletter->set("use_cronjob", 0); + } + } + + if (isset($_REQUEST["ckbDispatch"])) { + $oNewsletter->set("dispatch", 1); + } else { + $oNewsletter->set("dispatch", 0); + } + + $oNewsletter->set("dispatch_count", $_REQUEST["txtDispatchCount"]); + $oNewsletter->set("dispatch_delay", $_REQUEST["txtDispatchDelay"]); + + $oNewsletter->store(); // Note, that the properties are stored, anyway + // Storing from (e-mail), from (name) and options as default + if ($_REQUEST["ckbSetDefault"]) { + $oClientLang->setProperty("newsletter", "newsfrom", $sFromEMail); + $oClientLang->setProperty("newsletter", "newsfromname", $sFromName); + $oClientLang->setProperty("newsletter", "sendto", $_REQUEST["optSendTo"]); + $oClientLang->setProperty("newsletter", "sendgroups", serialize($_REQUEST["selGroup"])); + if (isset($_REQUEST["ckbCronJob"])) { + $oClientLang->setProperty("newsletter", "use_cronjob", "1"); + } else { + $oClientLang->setProperty("newsletter", "use_cronjob", "0"); + } + if (isset($_REQUEST["ckbDispatch"])) { + $oClientLang->setProperty("newsletter", "dispatch", "1"); + } else { + $oClientLang->setProperty("newsletter", "dispatch", "0"); + } + $oClientLang->setProperty("newsletter", "dispatchcount", $_REQUEST["txtDispatchCount"]); + $oClientLang->setProperty("newsletter", "dispatchdelay", $_REQUEST["txtDispatchDelay"]); + } + + if (count($aMessages) > 0) { + $notis .= $notification->returnNotification("warning", implode("
", $aMessages)) . "
"; + } + } else { + $_REQUEST["selGroup"] = unserialize($oNewsletter->get("send_ids")); + if (!is_array($_REQUEST["selGroup"])) { + $_REQUEST["selGroup"] = unserialize($oClientLang->getProperty("newsletter", "sendgroups")); + if (!is_array($_REQUEST["selGroup"])) { + $_REQUEST["selGroup"] = array(); + } + } + + $_REQUEST["ckbDispatch"] = false; + if ($oNewsletter->get("dispatch") == 1) { + $_REQUEST["ckbDispatch"] = true; + } else if ($oNewsletter->get("dispatch") == "" && $oClientLang->getProperty("newsletter", "dispatch") == "true") { + $_REQUEST["ckbDispatch"] = true; + } + } + + $oForm = new UI_Table_Form("properties"); + $oForm->setVar("frame", $frame); + $oForm->setVar("area", $area); + $oForm->setVar("action", "news_save"); + $oForm->setVar("idnewsletter", $oNewsletter->get("idnews")); + + $oForm->addHeader(i18n("Edit newsletter", "cl_newsletter")); + + $oTxtName = new cHTMLTextbox("txtName", $oNewsletter->get("name"), 40); + $oForm->add(i18n("Name", "cl_newsletter"), $oTxtName->render()); + + $oSelType = new cHTMLSelectElement("selType"); + $aItems = array(); + $aItems[] = array("text", i18n("Text only", "cl_newsletter")); + if ($oClientLang->getProperty("newsletter", "html_newsletter") == "true") { + $aItems[] = array("html", i18n("HTML and text", "cl_newsletter")); + } else { + $oNewsletter->set("type", "text"); // just in case the global setting was switched off + // TODO: Should this setting be stored? + } + $oSelType->autoFill($aItems); + $oSelType->setDefault($oNewsletter->get("type")); + + $oForm->add(i18n("Type", "cl_newsletter"), $oSelType->render()); + + $oTxtFromEMail = new cHTMLTextbox("txtFromEMail", $oNewsletter->get("newsfrom"), 40); + $oTxtFromName = new cHTMLTextbox("txtFromName", $oNewsletter->get("newsfromname"), 40); + $oTxtSubject = new cHTMLTextarea("txtSubject", $oNewsletter->get("subject"), 80, 2); + + $oForm->add(i18n("From (E-Mail)", "cl_newsletter"), $oTxtFromEMail->render()); + $oForm->add(i18n("From (Name)", "cl_newsletter"), $oTxtFromName->render() . " " . i18n("optional", "cl_newsletter")); + $oForm->add(i18n("Subject", "cl_newsletter"), $oTxtSubject->render()); + + // Send options + $oSendToAll = new cHTMLRadiobutton("optSendTo", "all"); + $oSendToAll->setEvent("Click", "checkSelection(this.value)"); + $oSendToDefault = new cHTMLRadiobutton("optSendTo", "default"); + $oSendToDefault->setEvent("Click", "checkSelection(this.value)"); + $oSendToGroups = new cHTMLRadiobutton("optSendTo", "selection"); + $oSendToGroups->setEvent("Click", "checkSelection(this.value)"); + + $oRcpGroups->setWhere("idclient", $client); + $oRcpGroups->setWhere("idlang", $lang); + $oRcpGroups->setOrder("defaultgroup DESC, groupname ASC"); + $oRcpGroups->query(); + + $aItems = array(); + while ($oRcpGroup = $oRcpGroups->next()) { + $sGroupName = $oRcpGroup->get("groupname"); + if ($oRcpGroup->get("defaultgroup")) { + $sGroupName = $sGroupName . "*"; + } + $aItems[] = array($oRcpGroup->get("idnewsgroup"), $sGroupName); + } + + $oSelGroup = new cHTMLSelectElement("selGroup[]", "", "groupselect"); + $oSelGroup->setSize(10); + $oSelGroup->setStyle("width: 350px; margin-top: 5px; margin-bottom: 5px; margin-left: 25px;"); + $oSelGroup->setMultiSelect(); + $oSelGroup->setAlt(i18n("Note: Hold to select multiple items.", "cl_newsletter")); + $oSelGroup->autoFill($aItems); + + // No groups in the list, sendToGroups and group listbox disabled + if (count($aItems) == 0) { + $oSendToGroups->setDisabled(true); + if ($_REQUEST["optSendTo"] == "selection") { + $_REQUEST["optSendTo"] == "all"; + } + } else if (is_array($_REQUEST["selGroup"])) { + foreach ($_REQUEST["selGroup"] as $sValue) { + if (array_key_exists($sValue, $oSelGroup->_options)) { + // only select, if item still exists + $oSelGroup->_options[$sValue]->setSelected(true); + } + } + } + + switch ($_REQUEST["optSendTo"]) { + case "default": + $oSendToDefault->setChecked(true); + $oSelGroup->setDisabled(true); + break; + case "selection": + $oSendToGroups->setChecked(true); + break; + default: + $oSendToAll->setChecked(true); + $oSelGroup->setDisabled(true); + } + + // Recipients + $oForm->add(i18n("Recipients", "cl_newsletter"), $oSendToAll->toHTML(false) . " " . i18n("Send newsletter to all recipients", "cl_newsletter") . "
" . chr(10) . + $oSendToDefault->toHTML(false) . " " . i18n("Send newsletter to the members of the default group", "cl_newsletter") . "
" . chr(10) . + $oSendToGroups->toHTML(false) . " " . i18n("Send newsletter to the members of the selected group(s):", "cl_newsletter") . "
" . chr(10) . + $oSelGroup->render()); + + /* TODO: Work in progress + // Files + $oSelFiles = new cHTMLSelectElement("selFiles[]", "", "fileselect"); + $oSelFiles->setSize(5); + //$oSelGroup->setStyle("width: 350px; margin-top: 5px; margin-bottom: 5px; margin-left: 25px;"); + $oSelFiles->setMultiSelect(); + $oSelFiles->setAlt(i18n("Note: Hold to select multiple items.")); + //$oSelGroup->autoFill($aItems); + $sFileSelScript = ''; + $oPage->addScript('selFile', $sFileSelScript); + $oForm->add(i18n("Attachments"), $oSelFiles->render().'
Test'); + */ + + // Options + $ckbWelcome = new cHTMLCheckbox("ckbWelcome", "1"); + $ckbWelcome->setChecked($oNewsletter->get("welcome")); + + // Generate disabled cronjob element + // Provide only "Use cronjob" option, if it has been explicitely enabled + // (and the admin knows, what he is doing - like using a real cronjob, not a simulated one...) + // Note, that the run_newsletter_job.php file has not been added to the cronjob + // list in the cronjobs folder - as it may be used, but not via cronjob simulation + $ckbCronJob = new cHTMLCheckbox("ckbCronJob", "1", "", $oNewsletter->get("use_cronjob"), true); + + if (getEffectiveSetting("newsletter", "option-cronjob-available", "false") == "true") { + // Enable cronjob checkbox + $ckbCronJob->setDisabled(""); + } else { + // Give the user a hint + $ckbCronJob->setAlt(i18n("Option has to be enabled as client setting - see techref for details", "cl_newsletter")); + } + + $oCkbDispatch = new cHTMLCheckbox("ckbDispatch", "enabled"); + $oCkbDispatch->setChecked($oNewsletter->get("dispatch")); + $oTxtDispatchCount = new cHTMLTextbox("txtDispatchCount", $oNewsletter->get("dispatch_count"), 4); + $oTxtDispatchDelay = new cHTMLTextbox("txtDispatchDelay", $oNewsletter->get("dispatch_delay"), 4); + $oTxtDispatchDelay->setAlt(i18n("Note: Set to 0 to send chunks manually.", "cl_newsletter")); + $oCkbSaveAsDefault = new cHTMLCheckbox("ckbSetDefault", "1"); + + $oForm->add(i18n("Options", "cl_newsletter"), $ckbWelcome->toHTML(false) . " " . i18n("Welcome-Newsletter", "cl_newsletter") . "
" . + $ckbCronJob->toHTML(false) . " " . i18n("Use cronjob", "cl_newsletter") . "
" . + $oCkbDispatch->toHTML(false) . " " . i18n("Send in blocks:", "cl_newsletter") . "   " . + i18n("Recipients per block:", "cl_newsletter") . " " . $oTxtDispatchCount->render() . " " . + i18n("Delay between blocks:", "cl_newsletter") . " " . $oTxtDispatchDelay->render() . " " . i18n("sec.", "cl_newsletter") . "
" . + $oCkbSaveAsDefault->toHTML(false) . " " . i18n("Save option settings as default", "cl_newsletter")); + + $oForm->add(i18n("Author", "cl_newsletter"), $classuser->getUserName($oNewsletter->get("author")) . " (" . $oNewsletter->get("created") . ")"); + $oForm->add(i18n("Last modified by", "cl_newsletter"), $classuser->getUserName($oNewsletter->get("modifiedby")) . " (" . $oNewsletter->get("modified") . ")"); + + $sExecScript = ' + '; + $oPage->addScript('exec', $sExecScript); + + $oPage->setContent($notis . $oForm->render(true)); +} else { + $oPage->setContent($notis . ""); +} + +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.newsletter_edit_message.php b/includes/include.newsletter_edit_message.php new file mode 100644 index 0000000..d8d6714 --- /dev/null +++ b/includes/include.newsletter_edit_message.php @@ -0,0 +1,257 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.newsletter_edit_message.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + +cInclude("includes", "functions.con.php"); // For conDeleteArt and conCopyArt +// Initialization +$oPage = new cPage; +$oClientLang = new cApiClientLanguage(false, $client, $lang); + +// Include plugins +if (is_array($cfg['plugins']['newsletters'])) { + foreach ($cfg['plugins']['newsletters'] as $plugin) { + plugin_include("newsletters", $plugin . "/" . $plugin . ".php"); + } +} + +// Exec actions +$oNewsletter = new Newsletter; +$oNewsletter->loadByPrimaryKey($idnewsletter); + +if ($oNewsletter->virgin == false && $oNewsletter->get("idclient") == $client && $oNewsletter->get("idlang") == $lang) { + // Check and set values + if (!is_numeric($_REQUEST["selTemplate"])) { + $_REQUEST["selTemplate"] = 0; + } + + // Saving message changes; note, that if a user doesn't have the right to save the + // text message he may still have the right to change the html article. To prevent + // changing the html article, give the user only read access right for the newsletter + // article category - the article will be shown also, if he doesn't have any rights at all... + if ($action == "news_save" && $perm->have_perm_area_action("news", $action)) { // Don't use $area! + // Changing e.g. \' back to ' (magic_quotes) + $sMessage = Contenido_Security::unescapeDB($_REQUEST["txtMessage"]); + $oNewsletter->set("message", $sMessage); + + if ($oNewsletter->get("template_idart") != $_REQUEST["selTemplate"]) { + if ($oNewsletter->get("idart") > 0) { + // Template has been changed: Delete old article + // (this discards the current html content as it deletes the existing newsletter article) + conDeleteArt($oNewsletter->get("idart")); + $iIDArt = 0; + } + + if ($_REQUEST["selTemplate"] > 0) { + // Template has been changed, but specified: Store template article as new newsletter article + $iIDArt = conCopyArticle($_REQUEST["selTemplate"], $oClientLang->getProperty("newsletter", "html_newsletter_idcat"), sprintf(i18n("Newsletter: %s", "cl_newsletter"), $oNewsletter->get("name"))); + conMakeOnline($iIDArt, $lang); // Article has to be online for sending... + } + + $oNewsletter->set("idart", $iIDArt); + $oNewsletter->set("template_idart", $_REQUEST["selTemplate"]); + } + + $oNewsletter->store(); + } else if ($oNewsletter->get("idart") > 0) { + // Check, if html message article and template article are still available + $oArticles = new cApiArticleLanguageCollection; + $oArticles->setWhere("idlang", $lang); + $oArticles->setWhere("idart", $oNewsletter->get("idart")); + $oArticles->query(); + + if ($oArticles->count() == 0) { + // Ups, article lost, reset idart and template_idart for newsletter + $notis = $notification->returnNotification("error", sprintf(i18n("The html newsletter article has been deleted (idart: %s), the html message is lost", "cl_newsletter"), $oNewsletter->get("idart"))) . "
"; + + $oNewsletter->set("idart", 0); + $oNewsletter->set("template_idart", 0); + $oNewsletter->store(); + } else { + $oArticles->resetQuery(); + $oArticles->setWhere("idlang", $lang); + $oArticles->setWhere("idart", $oNewsletter->get("template_idart")); + $oArticles->query(); + + if ($oArticles->count() == 0) { + // Ups, template has been deleted: Restore from current newsletter message article + $notis = $notification->returnNotification("warning", i18n("The html newsletter template article has been deleted, it has been restored using the html message article of this newsletter", "cl_newsletter")) . "
"; + + $iIDArt = conCopyArticle($oNewsletter->get("idart"), $oClientLang->getProperty("newsletter", "html_template_idcat"), sprintf(i18n("%s (Template restored)", "cl_newsletter"), $oNewsletter->get("name"))); + $oNewsletter->set("template_idart", $iIDArt); + $oNewsletter->store(); + } + } + } + + $oForm = new UI_Table_Form("frmNewsletterMsg"); + $oForm->setVar("frame", $frame); + $oForm->setVar("area", $area); + $oForm->setVar("action", "news_save"); + $oForm->setVar("idnewsletter", $idnewsletter); + $oForm->setWidth("100%"); + + $oForm->addHeader(sprintf(i18n("Edit newsletter message (%s)", "cl_newsletter"), $oNewsletter->get("name"))); + $oForm->add(i18n("Subject"), $oNewsletter->get("subject")); + + $sTagInfoText = '' . i18n("Tag information", "cl_newsletter") . '' . + '"; + + $iTplIDArt = 0; // Used later for on change event + if ($oNewsletter->get("type") == "html") { + $iTplIDArt = $oNewsletter->get("template_idart"); + $oSelTemplate = new cHTMLSelectElement("selTemplate"); + $oSelTemplate->setEvent("change", "askSubmitOnTplChange(this);"); + $aOptions = array("idcat" => $oClientLang->getProperty("newsletter", "html_template_idcat"), + "start" => true, + "offline" => true, + "order" => "title"); + $oTemplateArticles = new ArticleCollection($aOptions); + + $aItems = array(); + $aItems[] = array(0, i18n("-- none --", "cl_newsletter")); + while ($oArticle = $oTemplateArticles->nextArticle()) { + $aItems[] = array($oArticle->get("idart"), $oArticle->get("title")); + } + + $oSelTemplate->autoFill($aItems); + $oSelTemplate->setDefault($iTplIDArt); + unset($aItems); + unset($oArticles); + unset($oTemplateArticles); + + $oForm->add(i18n("HTML Template", "cl_newsletter"), $oSelTemplate->render() . " " . i18n("Note, that changing the template discards the current html message content", "cl_newsletter")); + + if ($iTplIDArt != 0) { + $sFrameSrc = $cfgClient[$client]["path"]["htmlpath"] . "front_content.php?changeview=edit&action=con_editart&idart=" . $oNewsletter->get("idart") . "&idcat=" . $oClientLang->getProperty("newsletter", "html_newsletter_idcat") . "&lang=" . $lang . "&contenido=" . $sess->id; + $oForm->add(i18n("HTML Message", "cl_newsletter"), '
' . $sTagInfoHTML); + } else { + // Add a real note, that a template has to be specified + $notis .= $notification->returnNotification("warning", i18n("Newsletter type has been set to HTML/text, please remember to select an html template", "cl_newsletter")) . "
"; + + $oForm->add(i18n("HTML Message", "cl_newsletter"), i18n("Please choose a template first", "cl_newsletter")); + } + } + + $oTxtMessage = new cHTMLTextarea("txtMessage", $oNewsletter->get("message"), 80, 20); + $oForm->add(i18n("Text Message", "cl_newsletter"), $oTxtMessage->render() . "
" . $sTagInfoText); + + $sExecScript = ' + '; + $oPage->addScript('messagebox', ''); + $oPage->addScript('execscript', $sExecScript); + $oPage->setContent($notis . $oForm->render(true)); +} else { + $oPage->setContent($notis . ""); +} + +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.newsletter_jobs_details.php b/includes/include.newsletter_jobs_details.php new file mode 100644 index 0000000..4be47c4 --- /dev/null +++ b/includes/include.newsletter_jobs_details.php @@ -0,0 +1,379 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.newsletter_jobs_details.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +// Initialization +$oPage = new cPage; + +if ($action == "news_job_run" && $perm->have_perm_area_action($area, $action) && is_numeric($_REQUEST["idnewsjob"])) { + // Run job + $oJob = new cNewsletterJob($_REQUEST["idnewsjob"]); + $iSendCount = $oJob->runJob(); + + if ($oJob->get("dispatch") == 1 && $oJob->get("sendcount") < $oJob->get("rcpcount")) { + // Send in chunks + $sPathNext = $sess->url("main.php?area=$area&action=news_job_run&frame=4&idnewsjob=" . $_REQUEST["idnewsjob"]); + + // Calculating some statistics + $iChunk = ceil($oJob->get("sendcount") / $oJob->get("dispatch_count")); + $iChunks = ceil($oJob->get("rcpcount") / $oJob->get("dispatch_count")); + + // Dispatch count > send/recipient count, set values to 1, at least + if ($iChunk == 0) { + $iChunk = 1; + } + if ($iChunks == 0) { + $iChunks = 1; + } + + if ($oJob->get("dispatch_delay") == 0) { + // Send manually + $oForm = new UI_Table_Form("properties", $sPathNext); + $oForm->addHeader(i18n("Report:", "cl_newsletter")); + $oForm->add("", ""); + + $oForm->add("", sprintf(i18n("Sending newsletter ... (chunk %s of %s, recipients: %s, sent: %s)", "cl_newsletter"), $iChunk, $iChunks, $oJob->get("rcpcount"), $oJob->get("sendcount"))); + + $oForm->setActionButton("cancel", $cfg['path']['contenido_fullhtml'] . "images/but_cancel.gif", i18n("Stop sending", "cl_newsletter"), "c"); + $oForm->setActionButton("submit", $cfg['path']['contenido_fullhtml'] . "images/but_ok.gif", i18n("Send next chunk", "cl_newsletter"), "s", "news_job_run"); + } else { + // Send automatically + $oForm = new UI_Table_Form("properties"); + $oForm->addHeader(i18n("Report:", "cl_newsletter")); + $oForm->add("", ""); + + $oForm->add("", sprintf(i18n("Sending newsletter ... (chunk %s of %s, recipients: %s, sent: %s)", "cl_newsletter"), $iChunk, $iChunks, $oJob->get("rcpcount"), $oJob->get("sendcount"))); + + $oPage->addScript("Refresh", ''); + $oForm->unsetActionButton("submit"); + $oForm->setActionButton("cancel", $cfg['path']['contenido_fullhtml'] . "images/but_cancel.gif", i18n("Stop sending", "cl_newsletter"), "c"); + } + } else { + // All newsletters should have been sent + $oForm = new UI_Table_Form("properties"); + $oForm->addHeader(i18n("Report:", "cl_newsletter")); + $oForm->add("", ""); + + $oForm->add("", sprintf(i18n("The newsletter has been sent to %s recipients", "cl_newsletter"), $oJob->get("sendcount"))); + $oPage->setReload(); + } + + $oPage->setContent($notis . $oForm->render(true)); +} else if ($action == "news_job_delete" && $perm->have_perm_area_action($area, $action) && is_numeric($_REQUEST["idnewsjob"])) { + $oJobs = new cNewsletterJobCollection; + $oJobs->delete($_REQUEST["idnewsjob"]); + + $oPage->setSubnav("blank", "news_jobs"); + $oPage->setReload(); + $oPage->setContent($notis); +} else if ($action == "news_job_details" || $action == "news_job_detail_delete") { + // Show job details (recipients) + + $oLogs = new cNewsletterLogCollection; + + // Remove recipient from a job + if ($action == "news_job_detail_delete" && is_numeric($_REQUEST["idnewslog"]) && $perm->have_perm_area_action($area, "news_job_detail_delete")) { + $oLogs->delete($_REQUEST["idnewslog"]); + } + + // Initialize + $iNextPage = Contenido_Security::toInteger($_GET['nextpage']); + if ($iNextPage <= 0) { + $iNextPage = 1; + } + + if ($_REQUEST["sortmode"] !== "DESC") { + $_REQUEST["sortmode"] = "ASC"; + } + + $sDateFormat = getEffectiveSetting("backend", "timeformat", "d.m.Y H:i"); + + // Set default values + $oUser = new cApiUser($auth->auth["uid"]); + if (!isset($_REQUEST["elemperpage"]) || !is_numeric($_REQUEST["elemperpage"]) || $_REQUEST["elemperpage"] < 0) { + $_REQUEST["elemperpage"] = $oUser->getProperty("itemsperpage", $area . "_job_details"); + } + if (!is_numeric($_REQUEST["elemperpage"])) { + $_REQUEST["elemperpage"] = 50; + } + if ($_REQUEST["elemperpage"] > 0) { + // - All - will not be saved + $oUser->setProperty("itemsperpage", $area . "_job_details", $_REQUEST["elemperpage"]); + } + + $oFrmOptions = new UI_Table_Form("frmOptions"); + $oFrmOptions->setVar("contenido", $sess->id); + $oFrmOptions->setVar("area", $area); + $oFrmOptions->setVar("action", $action); + $oFrmOptions->setVar("frame", $frame); + $oFrmOptions->setVar("sortmode", $_REQUEST["sortmode"]); + $oFrmOptions->setVar("sortby", $_REQUEST["sortby"]); + $oFrmOptions->setVar("idnewsjob", $_REQUEST["idnewsjob"]); + //$oFrmOptions->setVar("startpage", $startpage); + //$oFrmOptions->setVar("appendparameters", $appendparameters); + $oFrmOptions->addHeader(i18n("List options", "cl_newsletter")); + + $oSelElements = new cHTMLSelectElement("elemperpage"); + $oSelElements->setEvent("onchange", "document.forms.frmOptions.submit();"); + + $aData = Array("0" => i18n("-All-", "cl_newsletter"), + "50" => "50", + "100" => "100", + "250" => "250", + "500" => "500"); + + foreach ($aData as $sKey => $sValue) { + $oOption = new cHTMLOptionElement($sValue, $sKey); + $oSelElements->addOptionElement($sKey, $oOption); + } + + $oSelElements->setDefault($_REQUEST["elemperpage"]); + + //$oSelElements->setStyle('border:1px;border-style:solid;border-color:black;'); + $oFrmOptions->add(i18n("Items per page:", "cl_newsletter"), $oSelElements->render()); + + // Ouput data + $oList = new cScrollList(true, "news_job_details"); + $oList->setCustom("idnewsjob", $_REQUEST["idnewsjob"]); + $oList->setCustom("nextpage", $iNextPage); + $oList->setCustom("elemperpage", $_REQUEST["elemperpage"]); + + $aCols = array("rcpname", "rcpemail", "", "status", "sent"); + $oList->setHeader(i18n("Recipient", "cl_newsletter"), i18n("E-Mail", "cl_newsletter"), i18n("Type", "cl_newsletter"), i18n("Status", "cl_newsletter"), i18n("Sent", "cl_newsletter"), i18n("Actions", "cl_newsletter")); + $oList->setSortable(0, true); + $oList->setSortable(1, true); + $oList->setSortable(2, false); + $oList->setSortable(3, true); + $oList->setSortable(4, true); + + // Get data + $oLogs->resetQuery(); + $oLogs->setWhere("idnewsjob", $_REQUEST["idnewsjob"]); + + $sBrowseLinks = "1"; + if ($_REQUEST["elemperpage"] > 0) { + // First, get total data count + $oLogs->query(); + $iRecipients = $oLogs->count(); // Getting item count without limit (for page function) - better idea anybody (performance)? + + if ($iRecipients > 0 && $iRecipients > $_REQUEST["elemperpage"]) { + $sBrowseLinks = ""; + for ($i = 1; $i <= ceil($iRecipients / $_REQUEST["elemperpage"]); $i++) { + //$iNext = (($i - 1) * $_REQUEST["elemperpage"]) + 1; + if ($sBrowseLinks !== "") { + $sBrowseLinks .= " "; + } + if ($iNextPage == $i) { + $sBrowseLinks .= $i . "\n"; // I'm on the current page, no link + } else { + $sBrowseLinks .= '' . $i . '' . "\n"; + } + } + } + + $oLogs->setLimit($_REQUEST["elemperpage"] * ($iNextPage - 1), $_REQUEST["elemperpage"]); + } + + if (!array_key_exists($_REQUEST["sortby"], $aCols)) { + $_REQUEST["sortby"] = 0; // Sort by rcpname by default + } + $oLogs->setOrder($aCols[$_REQUEST["sortby"]] . " " . $_REQUEST["sortmode"]); + $oLogs->query(); + + $oImgDelete = new cHTMLImage("images/delete.gif"); + $oImgDelete->setAlt(i18n("Delete item", "cl_newsletter")); + $sImgDelete = $oImgDelete->render(); + unset($oImgDelete); + + $iCount = 0; + $aNewsType[] = array(); // Performance + $aNewsType[0] = i18n("Text only", "cl_newsletter"); + $aNewsType[1] = i18n("HTML/Text", "cl_newsletter"); + while ($oLog = $oLogs->next()) { + $sName = $oLog->get("rcpname"); + $sEMail = $oLog->get("rcpemail"); + + switch ($oLog->get("status")) { + case "pending": + $sStatus = i18n("Waiting for sending", "cl_newsletter"); + break; + case "sending": + $sStatus = i18n("Sending", "cl_newsletter"); + break; + case "successful": + $sStatus = i18n("Successful", "cl_newsletter"); + break; + default: + $sStatus = sprintf(i18n("Error: %s", "cl_newsletter"), $oLog->get("status")); + } + + if ($oLog->get("sent") == "0000-00-00 00:00:00") { + $sSent = "-"; + } else { + $sSent = date($sDateFormat, strtotime($oLog->get("sent"))); + } + + $sLnkRemove = ""; + if ($oLog->get("status") == "pending" && $perm->have_perm_area_action($area, "news_job_detail_delete")) { + $oLnkRemove = new cHTMLLink; + $oLnkRemove->setCLink("news_jobs", 4, "news_job_detail_delete"); + $oLnkRemove->setCustom("idnewsjob", $_REQUEST["idnewsjob"]); + $oLnkRemove->setCustom("idnewslog", $oLog->get($oLog->primaryKey)); + $oLnkRemove->setCustom("sortby", $_REQUEST["sortby"]); + $oLnkRemove->setCustom("sortmode", $_REQUEST["sortmode"]); + $oLnkRemove->setContent($sImgDelete); + + $sLnkRemove = $oLnkRemove->render(); + } + + $oList->setData($iCount, $sName, $sEMail, $aNewsType[$oLog->get("rcpnewstype")], $sStatus, $sSent, $sLnkRemove); + + $iCount++; + } + + // A little bit senseless, as the data is already sorted, but + // we need the sortmode in the header link + $oList->sort($_REQUEST["sortby"], $_REQUEST["sortmode"]); + + // HerrB: Hardcore UI for browsing elements ... sorry + $sBrowseHTML = ' + + + + + + +
' . + sprintf(i18n("Go to page: %s", "cl_newsletter"), $sBrowseLinks) . '
'; + + $oPage->setContent($oFrmOptions->render() . "
" . $oList->render() . $sBrowseHTML); +} else { + // Just show the job data + $oJob = new cNewsletterJob($_REQUEST["idnewsjob"]); + + $oForm = new UI_Table_Form("properties"); + $oForm->setVar("frame", $frame); + $oForm->setVar("area", $area); + $oForm->setVar("action", ""); + $oForm->setVar("idnewsjob", $idnewsjob); + + $oForm->addHeader(i18n("Newsletter Dispatch Job", "cl_newsletter")); + + $oForm->add(i18n("Name", "cl_newsletter"), $oJob->get("name")); + + $sDateFormat = getEffectiveSetting("backend", "timeformat", "d.m.Y H:i"); + switch ($oJob->get("status")) { + case 1: + $oForm->add(i18n("Status", "cl_newsletter"), i18n("Pending", "cl_newsletter")); + break; + case 2: + $oForm->add(i18n("Status", "cl_newsletter"), sprintf(i18n("Sending (started: %s)", "cl_newsletter"), date($sDateFormat, strtotime($oJob->get("started"))))); + break; + case 9: + $oForm->add(i18n("Status", "cl_newsletter"), sprintf(i18n("Finished (started: %s, finished: %s)", "cl_newsletter"), date($sDateFormat, strtotime($oJob->get("started"))), date($sDateFormat, strtotime($oJob->get("finished"))))); + break; + } + + $oForm->add(i18n("Statistics", "cl_newsletter"), sprintf(i18n("Planned: %s, Send: %s", "cl_newsletter"), $oJob->get("rcpcount"), $oJob->get("sendcount"))); + $oForm->add(i18n("From", "cl_newsletter"), $oJob->get("newsfrom") . " (" . $oJob->get("newsfromname") . ")"); + $oForm->add(i18n("Subject", "cl_newsletter"), $oJob->get("subject")); + + if ($oJob->get("type") == "html") { + $oForm->add(i18n("Type", "cl_newsletter"), i18n("HTML and text", "cl_newsletter")); + + $txtMessageHTML = new cHTMLTextarea("txtMessageHTML", $oJob->get("message_html"), 80, 20); + $txtMessageHTML->setDisabled("disabled"); + + $oForm->add(i18n("HTML Message", "cl_newsletter"), $txtMessageHTML->render()); + } else { + $oForm->add(i18n("Type", "cl_newsletter"), i18n("Text only", "cl_newsletter")); + } + $txtMessageText = new cHTMLTextarea("txtMessageText", $oJob->get("message_text"), 80, 20); + $txtMessageText->setDisabled("disabled"); + + $oForm->add(i18n("Text Message", "cl_newsletter"), $txtMessageText->render()); + + $aSendTo = unserialize($oJob->get("send_to")); + switch ($aSendTo[0]) { + case "all": + $sSendToInfo = i18n("Send newsletter to all recipients", "cl_newsletter"); + break; + case "default": + $sSendToInfo = i18n("Send newsletter to the members of the default group", "cl_newsletter"); + break; + case "selection": + $sSendToInfo = i18n("Send newsletter to the members of the selected group(s):", "cl_newsletter"); + + unset($aSendTo[0]); + foreach ($aSendTo as $sGroup) { + $sSendToInfo .= "
" . $sGroup; + } + break; + case "single": + $sSendToInfo = i18n("Send newsletter to single recipient:", "cl_newsletter"); + $sSendToInfo .= "
" . $aSendTo[1] . " (" . $aSendTo[2] . ")"; + break; + default: + } + unset($aSendTo); + + $oForm->add(i18n("Recipients", "cl_newsletter"), $sSendToInfo); + + if ($oJob->get("use_cronjob") == 1) { + $sOptionsInfo = i18n("Use cronjob: Enabled", "cl_newsletter"); + } else { + $sOptionsInfo = i18n("Use cronjob: Not enabled", "cl_newsletter"); + } + + if ($oJob->get("dispatch")) { + $sOptionsInfo .= "
" . sprintf(i18n("Dispatch: Enabled (block size: %s, delay: %s sec.)", "cl_newsletter"), $oJob->get("dispatch_count"), $oJob->get("dispatch_delay")); + } else { + $sOptionsInfo .= "
" . i18n("Dispatch: Disabled", "cl_newsletter"); + } + + $oForm->add(i18n("Options", "cl_newsletter"), $sOptionsInfo); + + $oForm->add(i18n("Author", "cl_newsletter"), $oJob->get("authorname")); + $oForm->add(i18n("Created", "cl_newsletter"), $oJob->get("created")); + + // Just remove the "save changes" message (as it is not possible to remove the image completely in ui_table_form) + $oForm->setActionButton("submit", $cfg['path']['contenido_fullhtml'] . "images/but_ok.gif", "", "s"); + + $oPage->setContent($oForm->render(true)); +} + +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.newsletter_jobs_menu.php b/includes/include.newsletter_jobs_menu.php new file mode 100644 index 0000000..60589b3 --- /dev/null +++ b/includes/include.newsletter_jobs_menu.php @@ -0,0 +1,344 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.newsletter_jobs_menu.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ + +if(!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +################################## +# Initialization +################################## +$oPage = new cPage; +$oMenu = new UI_Menu; +$oJobs = new cNewsletterJobCollection; +$oUser = new cApiUser($auth->auth["uid"]); + +// Specify fields for search, sort and validation. Design makes enhancements +// using plugins possible (currently not implemented). If you are changing things here, +// remember to update include.newsletter_left_top.php, also. +// field: Field name in the db +// caption: Shown field name (-> user) +// base: Elements from core code (other type may be: "plugin") +// sort: Element can be used to be sorted by +// search: Element can be used to search in +$aFields = array(); +$aFields["name"] = array("field" => "name", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); +$aFields["created"] = array("field" => "created", "caption" => i18n("Created", "cl_newsletter"), "type" => "base,sort"); +$aFields["status"] = array("field" => "status", "caption" => i18n("Status", "cl_newsletter"), "type" => "base,sort"); +// Not needed, as no sort/search, but keep as memo: $aFields["cronjob"] = array("field" => "use_cronjob", "caption" => i18n("Use cronjob"), "type" => "base"); + +################################## +# Check external input +################################## +// Items per page (value stored per area in user property) +if (!isset($_REQUEST["elemperpage"]) || !is_numeric($_REQUEST["elemperpage"]) || $_REQUEST["elemperpage"] < 0) { + $_REQUEST["elemperpage"] = $oUser->getProperty("itemsperpage", $area); +} +if (!is_numeric($_REQUEST["elemperpage"])) { + // This is the case, if the user property has never been set (first time user) + $_REQUEST["elemperpage"] = 25; +} +if ($_REQUEST["elemperpage"] > 0) { + // -- All -- will not be stored, as it may be impossible to change this back to something more useful + $oUser->setProperty("itemsperpage", $area, $_REQUEST["elemperpage"]); +} +unset ($oUser); + +$_REQUEST["page"] = (int)$_REQUEST["page"]; +if ($_REQUEST["page"] <= 0 || $_REQUEST["elemperpage"] == 0) { + $_REQUEST["page"] = 1; +} +// Sort order +if ($_REQUEST["sortorder"] != "ASC") { + $_REQUEST["sortorder"] = "DESC"; // Note, default is DESC (as default sortby is "created" date) +} + +// Check sort by and search in criteria +$bSortByFound = false; +$bSearchInFound = false; +foreach ($aFields as $sKey => $aData) +{ + if ($aData["field"] == $_REQUEST["sortby"] && strpos($aData["type"], "sort") !== false) { + $bSortByFound = true; + } + if ($aData["field"] == $_REQUEST["searchin"] && strpos($aData["type"], "search") !== false) { + $bSearchInFound = true; + } +} + +if (!$bSortByFound) { + $_REQUEST["sortby"] = "created"; // Default sort by field, possible values see above +} +if (!$bSearchInFound) { + $_REQUEST["searchin"] = "--all--"; +} + +// Author +if ($_REQUEST["selAuthor"] == "") { + $_REQUEST["selAuthor"] = $auth->auth["uid"]; +} + +// Free memory +unset($oUser); + +################################## +# Get data +################################## + +$oJobs->setWhere("idclient", $client); +$oJobs->setWhere("idlang", $lang); +$oJobs->setWhere("author", $_REQUEST["selAuthor"]); + +if ($_REQUEST["filter"] != "") +{ + if ($_REQUEST["searchin"] == "--all--" || $_REQUEST["searchin"] == "") + { + foreach ($aFields as $sKey => $aData) + { + if (strpos($aData["type"], "search") !== false) { + $oJobs->setWhereGroup("filter", $aData["field"], $_REQUEST["filter"], "LIKE"); + } + } + $oJobs->setInnerGroupCondition("filter", "OR"); + } else { + $oJobs->setWhere($_REQUEST["searchin"], $_REQUEST["filter"], "LIKE"); + } +} + +if ($_REQUEST["elemperpage"] > 0) +{ + $oJobs->query(); + + // Getting item count without limit (for page function) - better idea anyone (performance)? + $iItemCount = $oJobs->count(); + + if ($_REQUEST["elemperpage"]*($_REQUEST["page"]) >= $iItemCount+$_REQUEST["elemperpage"] && $_REQUEST["page"] != 1) { + $_REQUEST["page"]--; + } + $oJobs->setLimit($_REQUEST["elemperpage"] * ($_REQUEST["page"] - 1), $_REQUEST["elemperpage"]); +} else { + $iItemCount = 0; +} + +$oJobs->setOrder($_REQUEST["sortby"] . " " . $_REQUEST["sortorder"]); +$oJobs->query(); + +// Output data +$oMenu = new UI_Menu; +$iMenu = 0; +$sDateFormat = getEffectiveSetting("backend", "timeformat", "d.m.Y H:i"); + +// Store messages for repeated use (speeds performance, as i18n translation is only needed once) +$aMsg = array(); +$aMsg["DelTitle"] = i18n("Delete dispatch job", "cl_newsletter"); +$aMsg["DelDescr"] = i18n("Do you really want to delete the following newsletter dispatch job:
", "cl_newsletter"); + +$aMsg["SendTitle"] = i18n("Run job", "cl_newsletter"); +$aMsg["SendDescr"] = i18n("Do you really want to run the following job:
", "cl_newsletter"); + +// Prepare "send link" template +$sTplSend = ''.$aMsg['; + +while ($oJob = $oJobs->next()) +{ + $iMenu++; + $iID = $oJob->get("idnewsjob"); + $sName = $oJob->get("name") . " (" . date($sDateFormat, strtotime($oJob->get("created"))) .")"; + + $oLnk = new cHTMLLink; + $oLnk->setMultiLink($area, "", $area, ""); + $oLnk->setCustom("idnewsjob", $iID); + + // Is at present redundant + // HerrB: No, it's just not used/set... + //$oMenu->setImage($iMenu, "images/newsletter_16.gif"); + $oMenu->setTitle($iMenu, $sName); + + switch ($oJob->get("status")) + { + case 1: + // Pending + if ($oJob->get("cronjob") == 0) + { + // Standard job can be run if user has the right to do so + if ($perm->have_perm_area_action($area, "news_job_run")) + { + $sLnkSend = str_replace('{ID}', $iID, $sTplSend); + $sLnkSend = str_replace('{NAME}', addslashes($sName), $sLnkSend); + + $oMenu->setActions($iMenu, 'send', $sLnkSend); + } + } else if ($oJob->get("cronjob") == 1) { + // It's a cronjob job - no manual sending, show it blue + $oLnk->updateAttributes(array("style" => "color:#0000FF")); + } + + if ($perm->have_perm_area_action($area, "news_job_delete")) { + // Job may be deleted, if user has the right to do so + $oMenu->setActions($iMenu, 'delete', ''.$aMsg['); + } + break; + case 2: + // Sending job + if ($perm->have_perm_area_action($area, "news_job_run")) + { + // User may try to start sending, again - if he has the right to do so + $sLnkSend = str_replace('{ID}', $iID, $sTplSend); + $sLnkSend = str_replace('{NAME}', addslashes($sName), $sLnkSend); + + $oMenu->setActions($iMenu, 'send', $sLnkSend); + } + + $oLnk->updateAttributes(array("style" => "color:#da8a00")); + + $sDelete = ''.$aMsg['; + break; + case 9: + // Job finished, don't do anything + $oLnk->updateAttributes(array("style" => "color:#808080")); + + if ($perm->have_perm_area_action($area, "news_job_delete")) { + // You have the right, but you can't delete the job after sending + $oMenu->setActions($iMenu, 'delete', ''.$aMsg['); + } + break; + } + + $oMenu->setLink($iMenu, $oLnk); +} + +$sExecScript = ' + '; + +$oPage->setMargin(0); +// Messagebox JS has to be included before ExecScript! +$oPage->addScript('messagebox', ''); +$oPage->addScript('exec', $sExecScript); +$oPage->addScript('parameterCollector.js', ''); + +//generate current content for Object Pager +$sPagerId = '0ed6d632-6adf-4f09-a0c6-1e38ab60e303'; +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("selAuthor", $_REQUEST["selAuthor"]); +$oPagerLink->setCustom("elemperpage", $_REQUEST["elemperpage"]); +$oPagerLink->setCustom("filter", $_REQUEST["filter"]); +$oPagerLink->setCustom("restrictgroup", $_REQUEST["restrictgroup"]); +$oPagerLink->setCustom("sortby", $_REQUEST["sortby"]); +$oPagerLink->setCustom("sortorder", $_REQUEST["sortorder"]); +$oPagerLink->setCustom("searchin", $_REQUEST["searchin"]); +$oPagerLink->setCustom("frame", $frame); +$oPagerLink->setCustom("area", $area); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); +// Note, that after the "page" parameter no "pagerlink" parameter is specified - +// it is not used, as the JS below only uses the INNER html and the "pagerlink" parameter is +// set by ...left_top.html for the foldingrow itself +$oPager = new cObjectPager($sPagerId, $iItemCount, $_REQUEST["elemperpage"], $_REQUEST["page"], $oPagerLink, "page"); + +// Add slashes, to insert in javascript +$sPagerContent = $oPager->render(1); +$sPagerContent = str_replace('\\', '\\\\', $sPagerContent); +$sPagerContent = str_replace('\'', '\\\'', $sPagerContent); + +// Send new object pager to left_top +$oPage->addScript('setpager', ''); + +$sRefreshPager = ' + '; + +$oPage->addScript('refreshpager', $sRefreshPager); + +//$oPage->setContent(array('', $oListOptionRow, '
', $oMenu->render(false))); +$oPage->setContent($oMenu->render(false)); +$oPage->render(); + +?> \ No newline at end of file diff --git a/includes/include.newsletter_jobs_subnav.php b/includes/include.newsletter_jobs_subnav.php new file mode 100644 index 0000000..d24bcf5 --- /dev/null +++ b/includes/include.newsletter_jobs_subnav.php @@ -0,0 +1,67 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * modified 2010-05-20, Murat Purc, removed request check during processing ticket [#CON-307] + * + * $Id: include.newsletter_jobs_subnav.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ + +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +if (isset($_GET['idnewsjob']) && (int)$_GET['idnewsjob'] > 0) +{ + $sCaption = i18n("View", "cl_newsletter"); + $tmp_area = "foo2"; + + # Set template data + $tpl->set("d", "ID", 'c_'.$tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", ''.$sCaption.''); + $tpl->next(); + + $sCaption = i18n("Details", "cl_newsletter"); + $tmp_area = "foo2"; + + # Set template data + $tpl->set("d", "ID", 'c_'.$tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", ''.$sCaption.''); + $tpl->next(); + + $tpl->set('s', 'COLSPAN', ($tpl->dyn_cnt * 2) + 2); + + # Generate the third navigation layer + $tpl->generate($cfg["path"]["templates"] . $cfg["templates"]["subnav"]); +} else { + include ($cfg["path"]["contenido"].$cfg["path"]["templates"] . $cfg["templates"]["right_top_blank"]); +} + +?> \ No newline at end of file diff --git a/includes/include.newsletter_left_top.php b/includes/include.newsletter_left_top.php new file mode 100644 index 0000000..0c2e413 --- /dev/null +++ b/includes/include.newsletter_left_top.php @@ -0,0 +1,960 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * modified 2008-08-03, Bj�rn Behrens (HerrB), complete makeover to fix bugs and reduce memory waste + * + * $Id: include.newsletter_left_top.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ + +if(!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +###################################### +# Initialization +###################################### +if (!is_object($oTpl)) { + $oTpl = new Template; +} +if (!is_object($oDB)) { + $oDB = new DB_ConLite; // We have really to send a special SQL statement - we need a DB object +} + +$oUser = new cApiUser($auth->auth["uid"]); +$oClient = new cApiClient($client); +$oClientLang = new cApiClientLanguage(false, $client, $lang); + +###################################### +# 0. BUTTONS +###################################### +// Newsletter +$sId = 'img_newsletter'; +$oTpl->set('s', 'INEWSLETTER', $sId); +if ($perm->have_perm_area_action('news')) { + $sButtonRow = ''; + $sButtonRow .= ''. i18n('; + $sButtonRow .= ''; +} + +// Job dispatch +$sId = 'img_dispatch'; +$oTpl->set('s', 'IDISPATCH', $sId); +if ($perm->have_perm_area_action('news_jobs')) { + $sButtonRow .= ''; + $sButtonRow .= ''.i18n('; + $sButtonRow .= ''; +} + +// Recipients +$sId = 'img_recipient'; +$oTpl->set('s', 'IRECIPIENTS', $sId); +if ($perm->have_perm_area_action('recipients')) { + $sButtonRow .= ''; + $sButtonRow .= ''.i18n('; + $sButtonRow .= ''; +} + +// Recipient groups +$sId = 'img_recipientgroup'; +$oTpl->set('s', 'IRECIPIENTGROUP', $sId); +if ($perm->have_perm_area_action('recipientgroups')) { + $sButtonRow .= ''; + $sButtonRow .= ''.i18n('; + $sButtonRow .= ''; +} + +$oTpl->set('s', 'BUTTONROW', $sButtonRow); +unset($sButtonRow); + +###################################### +# 1. NEWSLETTER +###################################### + +###################################### +# 1.1 Newsletter: Actions folding row +###################################### +$sLink = "actionlink"; // ID for HTML element +$oActionsRow = new cFoldingRow("28cf9b31-e6d7-4657-a9a7-db31478e7a5c",i18n("Actions", "cl_newsletter"), $sLink); +$oTpl->set('s', 'ACTIONLINK', $sLink); + +if ($perm->have_perm_area_action("news", "news_create")) +{ + // Create the link to add a newsletter + $sContent = '
'."\n"; + + $oLink = new cHTMLLink; + $oLink->setMultiLink("news", "", "news", "news_create"); + $oLink->setContent(''.i18n("Create newsletter", "cl_newsletter")); + + $sContent .= $oLink->render() . '
'."\n"; + $oActionsRow->setContentData($sContent); +} else { + $oActionsRow->setContentData(""); +} + +###################################### +# 1.2 Newsletter: Settings folding row +###################################### +$sLink = "settingslink"; +$oSettingsRow = new cFoldingRow("d64baf0a-aea9-47b3-8490-54a00fce02b5",i18n("Settings", "cl_newsletter"), $sLink); +$oTpl->set('s', 'SETTINGSLINK', $sLink); + +// HTML Newsletter: Template and newsletter category +// Note, that in PHP 5 it is not possible to have a truely working copy of an object +// so, we are filling two almost identical objects with the same data ("clone" may work, but is not available in PHP4 ...) +$oSelHTMLTemplateIDCat = new cHTMLSelectElement("selHTMLTemplateCat"); +$oSelHTMLTemplateIDCat->setStyle("width: 220px;"); + +$oSelHTMLNewsletterIDCat = new cHTMLSelectElement("selHTMLNewsletterCat"); +$oSelHTMLNewsletterIDCat->setStyle("width: 220px;"); + +$oOptionTemplate = new cHTMLOptionElement("--".i18n("Please select", "cl_newsletter")."--", 0); +$oSelHTMLTemplateIDCat->addOptionElement(0, $oOptionTemplate); +$oOptionNewsletter = new cHTMLOptionElement("--".i18n("Please select", "cl_newsletter")."--", 0); +$oSelHTMLNewsletterIDCat->addOptionElement(0, $oOptionNewsletter); + +$sSQL = "SELECT tblCat.idcat AS idcat, tblCatLang.name AS name, tblCatTree.level AS level, "; +$sSQL .= "tblCatLang.visible AS visible, tblCatLang.public AS public FROM "; +$sSQL .= $cfg["tab"]["cat"]." AS tblCat, ".$cfg["tab"]["cat_lang"]." AS tblCatLang, "; +$sSQL .= $cfg["tab"]["cat_tree"]." AS tblCatTree "; +$sSQL .= "WHERE tblCat.idclient = '".Contenido_Security::toInteger($client)."' AND tblCatLang.idlang = '".Contenido_Security::toInteger($lang)."' AND "; +$sSQL .= "tblCatLang.idcat = tblCat.idcat AND tblCatTree.idcat = tblCat.idcat "; +$sSQL .= "ORDER BY tblCatTree.idtree"; + +$oDB->query($sSQL); + +while ($oDB->next_record()) { + $sSpaces = "  "; + + for ($i = 0; $i < $oDB->f("level"); $i ++) { + $sSpaces .= "     "; + } + + $oOptionTemplate = new cHTMLOptionElement($sSpaces.$oDB->f("name"), $oDB->f("idcat")); + $oOptionNewsletter = new cHTMLOptionElement($sSpaces.$oDB->f("name"), $oDB->f("idcat")); + if ($oDB->f("visible") == 0 || $oDB->f("public") == 0) { + $oOptionTemplate->setStyle("color: #666666;"); + $oOptionNewsletter->setStyle("color: #666666;"); + } + + $oSelHTMLTemplateIDCat->addOptionElement($oDB->f("idcat"), $oOptionTemplate); + $oSelHTMLNewsletterIDCat->addOptionElement($oDB->f("idcat"), $oOptionNewsletter); +} + +// Get html template category +$iHTMLTemplateIDCat = (int)$oClientLang->getProperty("newsletter", "html_template_idcat"); +if ($iHTMLTemplateIDCat < 0) { + $iHTMLTemplateIDCat = 0; +} +$oSelHTMLTemplateIDCat->setDefault($iHTMLTemplateIDCat); + +// Get html newsletter article category +$iHTMLNewsletterIDCat = (int)$oClientLang->getProperty("newsletter", "html_newsletter_idcat"); +if ($iHTMLNewsletterIDCat < 0) { + $iHTMLNewsletterIDCat = 0; +} +$oSelHTMLNewsletterIDCat->setDefault($iHTMLNewsletterIDCat); + +// Global HTML newsletter option +$bHTMLNewsletter = false; +if ($iHTMLTemplateIDCat > 0 && $iHTMLNewsletterIDCat > 0 && $oClientLang->getProperty("newsletter", "html_newsletter") == "true") { + // If necessary idcats are not specified or the option is disabled, + // then HTML are not used + $bHTMLNewsletter = true; +} +$oCkbHTMLNewsletter = new cHTMLCheckbox("ckbHTMLNewsletter", "enabled", "", $bHTMLNewsletter); + +// Disable HTML options, if user has no rights +if (!$perm->have_perm_area_action($area, "news_html_settings")) +{ + $oSelHTMLTemplateIDCat->setDisabled("disabled"); + $oSelHTMLNewsletterIDCat->setDisabled("disabled"); + $oCkbHTMLNewsletter->setDisabled("disabled"); +} + +// Destination for sending test newsletter +$oSelTestDestination = new cHTMLSelectElement("selTestDestination"); +$oSelTestDestination->setStyle("width: 220px;"); + +$oOption = new cHTMLOptionElement(i18n("My mail address", "cl_newsletter"), 0); +$oSelTestDestination->addOptionElement(0, $oOption); + +$oRcpGroups = new RecipientGroupCollection; +$oRcpGroups->setWhere("idclient", (int)$client); +$oRcpGroups->setWhere("idlang", (int)$lang); +$oRcpGroups->setOrder("groupname"); +$oRcpGroups->query(); + +$bTestTargetFound = false; +// Get client and language specific test destination. As lang is client specific, lang is sufficient +$iTestDestination = (int)$oUser->getProperty("newsletter", "test_idnewsgrp_lang" . $lang); +while ($oRcpGroup = $oRcpGroups->next()) +{ + $iID = $oRcpGroup->get($oRcpGroup->primaryKey); + + if ($iTestDestination == $iID) { + $bTestTargetFound = true; + } + + $oOption = new cHTMLOptionElement($oRcpGroup->get("groupname"), $iID); + $oSelTestDestination->addOptionElement($iID, $oOption); +} +unset($oRcpGroups); + +if (!$bTestTargetFound) { + // Currently specified test target doesn't exist anymore, get back to "my mail" + $iTestDestination = 0; +} +if (!$perm->have_perm_area_action($area, "news_send_test")) +{ + // No right to send somewhere else than to yourself + $iTestDestination = 0; + $oSelTestDestination->setDisabled("disabled"); +} +$oSelTestDestination->setDefault($iTestDestination); + +$oBtnSave = new cHTMLButton("submit", i18n("Save", "cl_newsletter")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'.$oCkbHTMLNewsletter->toHTML(false).' '.i18n("Enable HTML Newsletter", "cl_newsletter").'
'.i18n("HTML Template Category:", "cl_newsletter").'
'.$oSelHTMLTemplateIDCat->render().'
'.i18n("HTML Newsletter Category:", "cl_newsletter").'
'.$oSelHTMLNewsletterIDCat->render().'
'.i18n("Send test destination:", "cl_newsletter").'
'.$oSelTestDestination->render().'
'.$oBtnSave->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; +$oSettingsRow->setContentData($sContent); + +###################################### +# 1.3 Newsletter: List options folding row +###################################### +// Items per Page +$iItemsPerPage = (int)$oUser->getProperty("itemsperpage", "news"); // Also used in query below +if ($iItemsPerPage == 0) { + $iItemsPerPage = 25; // All can't be saved +} + +$oSelItemsPerPage = new cHTMLSelectElement("elemperpage"); +$oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); +$oSelItemsPerPage->setDefault($iItemsPerPage); +// Sort By +$oSelSortBy = new cHTMLSelectElement("sortby"); +$oOption = new cHTMLOptionElement("Name", "name"); +$oSelSortBy->addOptionElement($sKey, $oOption); +$oSelSortBy->setDefault("name"); +// Sort Order +$oSelSortOrder = new cHTMLSelectElement("sortorder"); +$oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); +$oSelSortOrder->setDefault("ASC"); +// Search For +$oTextboxFilter = new cHTMLTextbox("filter", "", 16); +// Search In +$oSelSearchIn = new cHTMLSelectElement("searchin"); +$oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); +$oSelSearchIn->addOptionElement("all", $oOption); +$oOption = new cHTMLOptionElement("Name", "name"); +$oSelSearchIn->addOptionElement($sKey, $oOption); +$oSelSearchIn->setDefault("name"); +// Apply button +$oBtnApply = new cHTMLButton("submit", i18n("Apply", "cl_newsletter")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'. i18n("Items / page", "cl_newsletter").''.$oSelItemsPerPage->render().'
'. i18n("Sort by", "cl_newsletter").''.$oSelSortBy->render().'
'. i18n("Sort order", "cl_newsletter").''.$oSelSortOrder->render().'
'. i18n("Search for", "cl_newsletter").''.$oTextboxFilter->render().'
'. i18n("Search in", "cl_newsletter").''.$oSelSearchIn->render().'
 '.$oBtnApply->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; + +// To template +$sLink = "listoption"; +$oListOptionsRow = new cFoldingRow("9d0968be-601d-44f8-a666-99d51c9c777d",i18n("List options", "cl_newsletter"), $sLink); +$oListOptionsRow->setContentData($sContent); +$oTpl->set('s', 'LISTOPTIONLINK', $sLink); + +###################################### +# 1.4 Newsletter: Paging folding row +###################################### + +// Add paging folding row (current page = 1) to get HTML paging container (later on updated by ...menu.php) +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame("left_bottom"); +$oPagerLink->setCustom("elemperpage", $iItemsPerPage); +$oPagerLink->setCustom("filter", ""); +//$oPagerLink->setCustom("restrictgroup", $_REQUEST["restrictgroup"]); +$oPagerLink->setCustom("sortby", "name"); +$oPagerLink->setCustom("sortorder", "ASC"); +$oPagerLink->setCustom("searchin", "name"); +$oPagerLink->setCustom("frame", "2"); +$oPagerLink->setCustom("area", "news"); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); + +$sLink = "pagerlink"; +$oTpl->set('s', 'PAGINGLINK', $sLink); +//$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e302", $iItemCount, $iItemsPerPage, 1, $oPagerLink, 'page', $sLink); +$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e302", 0, 1, 1, $oPagerLink, 'page', $sLink); + +###################################### +# Newsletter: Container +###################################### +$sContainerId = 'cont_newsletter'; +$sContainer = '
'; +$sContainer .= ''; +if ($perm->have_perm_area_action("news", "news_create")) { + $sContainer .= $oActionsRow->render(); +} +if ($perm->have_perm_area_action("news", "news_html_settings")) { + $sContainer .= $oSettingsRow->render(); +} +$sContainer .= $oListOptionsRow->render(); +$sContainer .= $oPagerRow->render(); +$sContainer .= '
'; +$sContainer .= '
'; +$oTpl->set('s', 'CNEWSLETTER', $sContainer); +$oTpl->set('s', 'ID_CNEWSLETTER', $sContainerId); + +###################################### +# 2. Job dispatch +###################################### +// Specify fields for search, sort and validation. Design makes enhancements +// using plugins possible (currently not implemented). If you are changing things here, +// remember to update include. ... menu.php, also. +// field: Field name in the db +// caption: Shown field name (-> user) +// base: Elements from core code (other type may be: "plugin") +// sort: Element can be used to be sorted by +// search: Element can be used to search in +$aFields = array(); +$aFields["name"] = array("field" => "name", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); +$aFields["created"] = array("field" => "created", "caption" => i18n("Created", "cl_newsletter"), "type" => "base,sort"); +$aFields["status"] = array("field" => "status", "caption" => i18n("Status", "cl_newsletter"), "type" => "base,sort"); +$aFields["cronjob"] = array("field" => "use_cronjob", "caption" => i18n("Use cronjob", "cl_newsletter"), "type" => "base"); + +###################################### +# 2.1 Job dispatch: List options folding row +###################################### +// Author +$oSelAuthor = new cHTMLSelectElement("selAuthor"); + +// Get possible authors/users from available jobs +// For this query genericdb can't be used, as the class id is always included (distinct won't work) +$sSQL = "SELECT DISTINCT author, authorname FROM ".$cfg["tab"]["news_jobs"]." ORDER BY authorname"; +$oDB->query($sSQL); + +$aItems = array(); +$bUserInList = false; +while ($oDB->next_record()) +{ + if ($oDB->f("author") == $auth->auth["uid"]) { + $bUserInList = true; + } + $aItems[] = array($oDB->f("author"), urldecode($oDB->f("authorname"))); +} +$oSelAuthor->autoFill($aItems); + +if (!$bUserInList) { + // Current ser hasn't sent newsletter jobs, yet - add him to the list (it's the default author) + $oOption = new cHTMLOptionElement($auth->auth["uname"], $auth->auth["uid"]); + $oSelAuthor->addOptionElement($auth->auth["uid"], $oOption); +} +$oSelAuthor->setDefault($auth->auth["uid"]); + +// Items per page +$iItemsPerPage = (int)$oUser->getProperty("itemsperpage", "news_jobs"); // Used also below in query +if ($iItemsPerPage == 0) { + $iItemsPerPage = 25; // All can't be saved +} + +$oSelItemsPerPage = new cHTMLSelectElement("elemperpage"); +$oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); +$oSelItemsPerPage->setDefault($iItemsPerPage); + +// Sort by +$oSelSortBy = new cHTMLSelectElement("sortby"); +foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "sort") !== false) + { + $oOption = new cHTMLOptionElement($aData["caption"], $sKey); + $oSelSortBy->addOptionElement($sKey, $oOption); + } +} +$oSelSortBy->setDefault("created"); + +// Sort order +$oSelSortOrder = new cHTMLSelectElement("sortorder"); +$oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); +$oSelSortOrder->setDefault("DESC"); + +// Filter +$oTxtFilter = new cHTMLTextbox("filter", "", 16); + +//Search in +$oSelSearchIn = new cHTMLSelectElement("searchin"); +$oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); +$oSelSearchIn->addOptionElement("all", $oOption); + +foreach ($aFields as $sKey => $aData) +{ + if (strpos($aData["type"], "search") !== false) + { + $oOption = new cHTMLOptionElement($aData["caption"], $sKey); + $oSelSearchIn->addOptionElement($sKey, $oOption); + } +} +$oSelSearchIn->setDefault("--all--"); + +$oBtnApply = new cHTMLButton("submit", i18n("Apply", "cl_newsletter")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'. i18n("Author", "cl_newsletter").''.$oSelAuthor->render().'
'. i18n("Items / page", "cl_newsletter").''.$oSelItemsPerPage->render().'
'. i18n("Sort by", "cl_newsletter").''.$oSelSortBy->render().'
'. i18n("Sort order", "cl_newsletter").''.$oSelSortOrder->render().'
'. i18n("Search for", "cl_newsletter").''.$oTxtFilter->render().'
'. i18n("Search in", "cl_newsletter").''.$oSelSearchIn->render().'
 '.$oBtnApply->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; + +// To template +$sLink = "listoptiondisp"; +$oListOptionsRow = new cFoldingRow("dfa6cc00-0acf-11db-9cd8-0800200c9a66",i18n("List options", "cl_newsletter"), $sLink); +$oListOptionsRow->setContentData($sContent); +$oTpl->set('s', 'LISTOPTIONLINKDISP', $sLink); + +###################################### +# 2.2 Job dispatch: Paging folding row +###################################### +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("selAuthor", $auth->auth["uid"]); +$oPagerLink->setCustom("elemperpage", $iItemsPerPage); +$oPagerLink->setCustom("filter", ""); +//$oPagerLink->setCustom("restrictgroup", $_REQUEST["restrictgroup"]); +$oPagerLink->setCustom("sortby", "created"); +$oPagerLink->setCustom("sortorder", "DESC"); +$oPagerLink->setCustom("searchin", "--all--"); +$oPagerLink->setCustom("frame", "2"); // HIER!!! Stimmt das? +$oPagerLink->setCustom("area", "news_jobs"); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); + +$sLink = "pagerlinkdisp"; +$oTpl->set('s', 'PAGINGLINKDISP', $sLink); +//$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e303", $iItemCount, $iItemsPerPage, 1, $oPagerLink, "page", $sLink); +$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e303", 0, 1, 1, $oPagerLink, 'page', $sLink); + +###################################### +# Job dispatch: Container +###################################### +$sContainerId = 'cont_dispatch'; +$sContainer = '
'; +$sContainer .= ''; +$sContainer .= $oListOptionsRow->render(); +$sContainer .= $oPagerRow->render(); +$sContainer .= '
'; +$sContainer .= '
'; +$oTpl->set('s', 'CDISPATCH', $sContainer); +$oTpl->set('s', 'ID_CDISPATCH', $sContainerId); + +###################################### +# 3. Recipients +###################################### +// See comment at 2. Job dispatch +$aFields = array(); +$aFields["name"] = array("field" => "name", "caption" => i18n("Name", "cl_newsletter"),"type" => "base,sort,search"); +$aFields["email"] = array("field" => "email", "caption" => i18n("E-Mail", "cl_newsletter"),"type" => "base,sort,search"); +$aFields["confirmed"] = array("field" => "confirmed", "caption" => i18n("Confirmed", "cl_newsletter"), "type" => "base"); +$aFields["deactivated"] = array("field" => "deactivated", "caption" => i18n("Deactivated", "cl_newsletter"), "type" => "base"); + +###################################### +# 3.1 Recipients: Actions folding row +###################################### +$sContent = '
'."\n"; + +// Create a link to add a recipient +if ($perm->have_perm_area_action("recipients", "recipients_create")) +{ + $oLink = new cHTMLLink; + $oLink->setMultiLink("recipients","","recipients","recipients_create"); + $oLink->setContent(''.i18n("Create recipient", "cl_newsletter").''); + + $sContent .= $oLink->render().'
'."\n"; +} + +// Create a link to import recipients +if ($perm->have_perm_area_action("recipients", "recipients_create")) +{ + $oLink = new cHTMLLink; + $oLink->setMultiLink("recipients", "", "recipients_import", "recipients_import"); + $oLink->setContent(''.i18n("Import recipients", "cl_newsletter").''); + + $sContent .= $oLink->render().'
'."\n"; +} + +// Create a link to purge subscribed but not confirmed recipients +$iTimeframe = (int)$oClient->getProperty("newsletter", "purgetimeframe"); +if ($iTimeframe <= 0) { + $iTimeframe = 30; +} + +if ($perm->have_perm_area_action("recipients", "recipients_delete")) +{ + $oLink = new cHTMLLink; + $oLink->setLink('javascript:showPurgeMsg("'.i18n('Purge recipients', "cl_newsletter").'", "'.sprintf(i18n("Do you really want to remove recipients, that have not been confirmed since %s days and over?", "cl_newsletter"), '"+purgetimeframe+"').'")'); + + $oLink->setContent(''.i18n("Purge recipients", "cl_newsletter").''); + + $sContent .= $oLink->render(); +} +$sContent .= '
'."\n"; +$oTpl->set('s', 'VALUE_PURGETIMEFRAME', $iTimeframe); + +// To template +$sLink = "actionrec"; +$oListActionsRow = new cFoldingRow("f0d7bf80-e73e-11d9-8cd6-0800200c9a66", i18n("Actions", "cl_newsletter"), $sLink); +$oListActionsRow->setContentData($sContent); +$oTpl->set('s', 'ACTIONLINKREC', $sLink); + +###################################### +# 3.2 Recipients: Settings folding row +###################################### +$oTxtTimeframe = new cHTMLTextbox("txtPurgeTimeframe", $iTimeframe, 5); +$oBtnSave = new cHTMLButton("submit", i18n("Save", "cl_newsletter")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'. i18n("Purge timeframe", "cl_newsletter").':'.$oTxtTimeframe->render().' '.i18n("days", "cl_newsletter").'
 '.$oBtnSave->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; + +// To template +$sLink = "settingsrec"; +$oSettingsRow = new cFoldingRow("5ddbe820-e6f1-11d9-8cd6-0800200c9a69",i18n("Settings", "cl_newsletter"), $sLink); +$oSettingsRow->setContentData($sContent); +$oTpl->set('s', 'SETTINGSLINKREC', $sLink); + +###################################### +# 3.3 Recipients: List options folding row +###################################### +$iItemsPerPage = (int)$oUser->getProperty("itemsperpage", "recipients"); +if ($iItemsPerPage == 0) { + $iItemsPerPage = 25; // All can't be saved +} + +$oSelItemsPerPage = new cHTMLSelectElement("elemperpage"); +$oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); +$oSelItemsPerPage->setDefault($iItemsPerPage); + +$oSelSortBy = new cHTMLSelectElement("sortby"); +foreach ($aFields as $sKey => $aData) +{ + if (strpos($aData["type"], "sort") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSortBy->addOptionElement($aData["field"], $oOption); + } +} +$oSelSortBy->setDefault("name"); + +$oSelSortOrder = new cHTMLSelectElement("sortorder"); +$oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); +$oSelSortOrder->setDefault("ASC"); + +$oSelRestrictGroup = new cHTMLSelectElement("restrictgroup"); +$oOption = new cHTMLOptionElement(i18n("-- All groups --", "cl_newsletter"), "--all--"); +$oSelRestrictGroup->addOptionElement("all", $oOption); + +// Fetch recipient groups +$oRGroups = new RecipientGroupCollection; +$oRGroups->setWhere("idclient", $client); +$oRGroups->setWhere("idlang", $lang); +$oRGroups->setOrder("defaultgroup DESC, groupname ASC"); +$oRGroups->query(); + +$i = 1; +while ($oRGroup = $oRGroups->next()) +{ + if ($oRGroup->get("defaultgroup") == 1) { + $sGroupname = $oRGroup->get("groupname") . "*"; + } else { + $sGroupname = $oRGroup->get("groupname"); + } + $oOption = new cHTMLOptionElement($sGroupname, $oRGroup->get("idnewsgroup")); + $oSelRestrictGroup->addOptionElement($i, $oOption); + $i++; +} + +$oSelRestrictGroup->setDefault("--all--"); + +$oTxtFilter = new cHTMLTextbox("filter", "", 16); + +$oSelSearchIn = new cHTMLSelectElement("searchin"); +$oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); +$oSelSearchIn->addOptionElement("all", $oOption); + +foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSearchIn->addOptionElement($aData["field"], $oOption); + } +} +$oSelSearchIn->setDefault("--all--"); + +$oBtnApply = new cHTMLButton("submit", i18n("Apply")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'. i18n("Items / page", "cl_newsletter").''.$oSelItemsPerPage->render().'
'. i18n("Sort by", "cl_newsletter").''.$oSelSortBy->render().'
'. i18n("Sort order", "cl_newsletter").''.$oSelSortOrder->render().'
'. i18n("Show group", "cl_newsletter").''.$oSelRestrictGroup->render().'
'. i18n("Search for", "cl_newsletter").''.$oTxtFilter->render().'
'. i18n("Search in", "cl_newsletter").''.$oSelSearchIn->render().'
 '.$oBtnApply->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; + +// To template +$sLink = "listoptionsrec"; +$oListOptionsRow = new cFoldingRow("5ddbe820-e6f1-11d9-8cd6-0800200c9a66",i18n("List options", "cl_newsletter"), $sLink); +$oListOptionsRow->setContentData($sContent); +$oTpl->set('s', 'LISTOPTIONLINKREC', $sLink); + +###################################### +# 3.4 Recipients: Paging +###################################### +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("elemperpage", $iItemsPerPage); +$oPagerLink->setCustom("filter", ""); +$oPagerLink->setCustom("restrictgroup", "--all--"); +$oPagerLink->setCustom("sortby", "name"); +$oPagerLink->setCustom("sortorder", "ASC"); +$oPagerLink->setCustom("searchin", "--all--"); +$oPagerLink->setCustom("frame", "2"); +$oPagerLink->setCustom("area", "recipients"); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); + +// To template +$sLink = "pagingrec"; +$oTpl->set('s', 'PAGINGLINKREC', $sLink); +//$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e304", $iItemCount, $iItemsPerPage, 1, $oPagerLink, "page", $sLink); +$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e304", 0, 1, 1, $oPagerLink, 'page', $sLink); + +###################################### +# Recipients: Container +###################################### +$sContainerId = 'cont_recipients'; +$sContainer = '
'; +$sContainer .= ''; +if ($perm->have_perm_area_action('recipients', "recipients_delete") || $perm->have_perm_area_action("recipients", "recipients_create")) { + $sContainer .= $oListActionsRow->render(); +} +$sContainer .= $oSettingsRow->render(); +$sContainer .= $oListOptionsRow->render(); +$sContainer .= $oPagerRow->render(); +$sContainer .= '
'; +$sContainer .= '
'; +$oTpl->set('s', 'CRECIPIENTS', $sContainer); +$oTpl->set('s', 'ID_CRECIPIENTS', $sContainerId); + +###################################### +# 4 Recipient groups +###################################### +// See comment at 2. Job dispatch +$aFields = array(); +$aFields["name"] = array("field" => "groupname", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); + +###################################### +# 4.1 Recipient groups: Actions +###################################### +$sContent = '
'."\n"; + +// Create a link to add a group +if ($perm->have_perm_area_action("recipientgroups", "recipientgroup_create")) +{ + $oLnk = new cHTMLLink; + $oLnk->setMultiLink("recipientgroups","","recipientgroups","recipientgroup_create"); + $oLnk->setContent(''.i18n("Create group", "cl_newsletter").''); + $sContent .= $oLnk->render().'
'."\n"; +} + +$sContent .= '
'."\n"; + +$sLink = "actiongroup"; +$oListActionsRow = new cFoldingRow("f0d7bf80-e73e-11d9-8cd6-0800200c9a67",i18n("Actions", "cl_newsletter"), $sLink); +$oListActionsRow->setContentData($sContent); +$oTpl->set('s', 'ACTIONLINKGROUP', $sLink); + +###################################### +# 4.2 Recipient groups: List Options +###################################### +$iItemsPerPage = (int)$oUser->getProperty("itemsperpage", "recipientgroups"); +if ($iItemsPerPage == 0) { + $iItemsPerPage = 25; // All can't be saved +} + +$oSelItemsPerPage = new cHTMLSelectElement("elemperpage"); +$oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); +$oSelItemsPerPage->setDefault($iItemsPerPage); + +$oSelSortBy = new cHTMLSelectElement("sortby"); +foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "sort") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSortBy->addOptionElement($aData["field"], $oOption); + } +} +$oSelSortBy->setDefault("name"); + +$oSelSortOrder = new cHTMLSelectElement("sortorder"); +$oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); +$oSelSortOrder->setDefault("ASC"); + +$oTxtFilter = new cHTMLTextbox("filter", "", 16); + +$oSelSearchIn = new cHTMLSelectElement("searchin"); +$oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); +$oSelSearchIn->addOptionElement("all", $oOption); + +foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSearchIn->addOptionElement($aData["field"], $oOption); + } +} +$oSelSearchIn->setDefault("--all--"); + +$oBtnApply = new cHTMLButton("submit", i18n("Apply", "cl_newsletter")); + +$sContent = '
'."\n"; +$sContent .= '
'."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= ' '."\n"; +$sContent .= '
'. i18n("Items / page", "cl_newsletter").''.$oSelItemsPerPage->render().'
'. i18n("Sort by", "cl_newsletter").''.$oSelSortBy->render().'
'. i18n("Sort order", "cl_newsletter").''.$oSelSortOrder->render().'
'. i18n("Search for", "cl_newsletter").''.$oTxtFilter->render().'
'. i18n("Search in", "cl_newsletter").''.$oSelSearchIn->render().'
 '.$oBtnApply->render().'
'."\n"; +$sContent .= '
'."\n"; +$sContent .= '
'."\n"; + +// To template +$sLink = "listoptionsgroup"; +$oListOptionsRow = new cFoldingRow("79efc1fc-111d-11dc-8314-0800200c9a66",i18n("List options", "cl_newsletter"), $sLink); +$oListOptionsRow->setContentData($sContent); +$oTpl->set('s', 'LISTOPTIONLINKGROUP', $sLink); + +###################################### +# 4.3 Recipient groups: Paging +###################################### +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("elemperpage", $iItemsPerPage); +$oPagerLink->setCustom("filter", ""); +$oPagerLink->setCustom("sortby", "name"); +$oPagerLink->setCustom("sortorder", "ASC"); +$oPagerLink->setCustom("searchin", "--all--"); +$oPagerLink->setCustom("frame", "2"); +$oPagerLink->setCustom("area", "recipientgroups"); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); + +// To template +$sLink = "paginggroup"; +$oTpl->set('s', 'PAGINGLINKGROUP', $sLink); +//$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e305", $iItemCount, $iItemsPerPage, 1, $oPagerLink, "page", $sLink); +$oPagerRow = new cObjectPager("0ed6d632-6adf-4f09-a0c6-1e38ab60e305", 0, 1, 1, $oPagerLink, 'page', $sLink); + +###################################### +# Recipient Groups: Container +###################################### +$sContainerId = 'cont_recipientgroup'; +$sContainer = '
'; +$sContainer .= ''; +if ($perm->have_perm_area_action("recipientgroups", "recipientgroup_create")) { + $sContainer .= $oListActionsRow->render(); +} +$sContainer .= $oListOptionsRow->render(); +$sContainer .= $oPagerRow->render(); +$sContainer .= '
'; +$sContainer .= '
'; +$oTpl->set('s', 'CRECIPIENTGROUP', $sContainer); +$oTpl->set('s', 'ID_CRECIPIENTGROUP', $sContainerId); + +$oTpl->set('s', 'SESSID', $sess->id); +$oTpl->generate($cfg['path']['templates'] . $cfg['templates']['newsletter_left_top']); + +?> \ No newline at end of file diff --git a/includes/include.newsletter_menu.php b/includes/include.newsletter_menu.php new file mode 100644 index 0000000..677a1f9 --- /dev/null +++ b/includes/include.newsletter_menu.php @@ -0,0 +1,367 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.newsletter_menu.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +################################## +# Initialization +################################## +$oPage = new cPage; +$oUser = new cApiUser($auth->auth["uid"]); +$oClientLang = new cApiClientLanguage(false, $client, $lang); + +// Get idCatArt to check, if we may send a test newsletter +$lIDCatArt = (int) $oClientLang->getProperty("newsletter", "idcatart"); + +// Specify fields for search, sort and validation. Design makes enhancements +// using plugins possible (currently not implemented). If you are changing things here, +// remember to update include.newsletter_left_top.php, also. +// field: Field name in the db +// caption: Shown field name (-> user) +// base: Elements from core code (other type may be: "plugin") +// sort: Element can be used to be sorted by +// search: Element can be used to search in +$aFields = array(); +$aFields["name"] = array("field" => "name", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); + +################################## +# Store settings/Get basic data +################################## +if (isset($_REQUEST['action_html']) && $_REQUEST['action_html'] == 'save_newsletter_properties' && $perm->have_perm_area_action($area, "news_html_settings")) { + // Storing settings + if (isset($_REQUEST["ckbHTMLNewsletter"])) { + $oClientLang->setProperty("newsletter", "html_newsletter", "true"); + } else { + $oClientLang->setProperty("newsletter", "html_newsletter", "false"); + } + $oClientLang->setProperty("newsletter", "html_template_idcat", (int) $_REQUEST["selHTMLTemplateCat"]); + $oClientLang->setProperty("newsletter", "html_newsletter_idcat", (int) $_REQUEST["selHTMLNewsletterCat"]); + $oUser->setProperty("newsletter", "test_idnewsgrp_lang" . $lang, (int) $_REQUEST["selTestDestination"]); +} else { + // No settings to be stored, get current settings (language sepcific, as lang is client specific, lang is sufficient) + $_REQUEST["selTestDestination"] = (int) $oUser->getProperty("newsletter", "test_idnewsgrp_lang" . $lang); +} +// Default value: Current user mail +$sSendTestTarget = $oUser->get("realname") . " (" . $oUser->get("email") . ")"; + +################################## +# Check external input +################################## +// Items per page (value stored per area in user property) +if (!isset($_REQUEST["elemperpage"]) || !is_numeric($_REQUEST["elemperpage"]) || $_REQUEST["elemperpage"] < 0) { + $_REQUEST["elemperpage"] = $oUser->getProperty("itemsperpage", $area); +} +if (!is_numeric($_REQUEST["elemperpage"])) { + // This is the case, if the user property has never been set (first time user) + $_REQUEST["elemperpage"] = 25; +} +if ($_REQUEST["elemperpage"] > 0) { + // -- All -- will not be stored, as it may be impossible to change this back to something more useful + $oUser->setProperty("itemsperpage", $area, $_REQUEST["elemperpage"]); +} +$_REQUEST["page"] = (int) $_REQUEST["page"]; +if ($_REQUEST["page"] <= 0 || $_REQUEST["elemperpage"] == 0) { + $_REQUEST["page"] = 1; +} +// Sort order +if ($_REQUEST["sortorder"] != "DESC") { + $_REQUEST["sortorder"] = "ASC"; +} + +// Check sort by and search in criteria +$bSortByFound = false; +$bSearchInFound = false; +foreach ($aFields as $sKey => $aData) { + if ($aData["field"] == $_REQUEST["sortby"] && strpos($aData["type"], "sort") !== false) { + $bSortByFound = true; + } + if ($aData["field"] == $_REQUEST["searchin"] && strpos($aData["type"], "search") !== false) { + $bSearchInFound = true; + } +} + +if (!$bSortByFound) { + $_REQUEST["sortby"] = "name"; // Default sort by field, possible values see above +} +if (!$bSearchInFound) { + $_REQUEST["searchin"] = "--all--"; +} + +// Free memory +unset($oClientLang); +unset($oUser); + +################################## +# Get data +################################## +$oNewsletters = new NewsletterCollection; +$oNewsletters->setWhere("idclient", $client); +$oNewsletters->setWhere("idlang", $lang); + +if ($_REQUEST["filter"] != "") { + if ($_REQUEST["searchin"] == "--all--" || $_REQUEST["searchin"] == "") { + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oNewsletters->setWhereGroup("filter", $aData["field"], $_REQUEST["filter"], "LIKE"); + } + } + $oNewsletters->setInnerGroupCondition("filter", "OR"); + } else { + $oNewsletters->setWhere($_REQUEST["searchin"], $_REQUEST["filter"], "LIKE"); + } +} + +if ($_REQUEST["elemperpage"] > 0) { + // Getting item count without limit (for page function) - better idea anyone (performance)? + $oNewsletters->query(); + $iItemCount = $oNewsletters->count(); + + if ($_REQUEST["elemperpage"] * ($_REQUEST["page"]) >= $iItemCount + $_REQUEST["elemperpage"] && $_REQUEST["page"] != 1) { + $_REQUEST["page"] --; + } + + $oNewsletters->setLimit($_REQUEST["elemperpage"] * ($_REQUEST["page"] - 1), $_REQUEST["elemperpage"]); +} else { + $iItemCount = 0; +} + +$oNewsletters->setOrder("welcome DESC, " . $_REQUEST["sortby"] . " " . $_REQUEST["sortorder"]); +$oNewsletters->query(); + +// Output data +$oMenu = new UI_Menu; +$iMenu = 0; + +// Store messages for repeated use (speeds performance, as i18n translation is only needed once) +$aMsg = array(); +$aMsg["DelTitle"] = i18n("Delete newsletter", "cl_newsletter"); +$aMsg["DelDescr"] = i18n("Do you really want to delete the following newsletter:
", "cl_newsletter"); + +$aMsg["SendTestTitle"] = i18n("Send test newsletter", "cl_newsletter"); +$aMsg["SendTestTitleOff"] = i18n("Send test newsletter (disabled, check newsletter sender e-mail address and handler article selection)", "cl_newsletter"); +$aMsg["AddJobTitle"] = i18n("Add newsletter dispatch job", "cl_newsletter"); +$aMsg["AddJobTitleOff"] = i18n("Add newsletter dispatch job (disabled, check newsletter sender e-mail address and handler article selection)", "cl_newsletter"); +$aMsg["CopyTitle"] = i18n("Duplicate newsletter", "cl_newsletter"); + +while ($oNewsletter = $oNewsletters->next()) { + $idnewsletter = $oNewsletter->get("idnews"); + $iMenu++; + + $sName = $oNewsletter->get("name"); + if ($oNewsletter->get("welcome")) { + $sName = $sName . "*"; + } + + // Create the link to show/edit the newsletter + $oLnk = new cHTMLLink; + $oLnk->setMultiLink($area, "", $area, ""); + $oLnk->setCustom("idnewsletter", $idnewsletter); + + $oMenu->setTitle($iMenu, $sName); + $oMenu->setLink($iMenu, $oLnk); + + if ($perm->have_perm_area_action($area, "news_add_job") || + $perm->have_perm_area_action($area, "news_create") || + $perm->have_perm_area_action($area, "news_save")) { + // Rights: If you are able to add a job, you should be able to test it + // If you are able to add or change a newsletter, you should be able to test it + // Usability: If no e-mail has been specified, you can't send a test newsletter + if (isValidMail($oNewsletter->get("newsfrom")) && $lIDCatArt > 0) { + $sLnkSendTest = '' . $aMsg['; + } else { + $sLnkSendTest = '' . $aMsg['; + } + $oMenu->setActions($iMenu, 'test', $sLnkSendTest); + } + + if ($perm->have_perm_area_action($area, "news_add_job")) { + if (isValidMail($oNewsletter->get("newsfrom")) && $lIDCatArt > 0) { + $oLnkAddJob = new Link; + $oLnkAddJob->setMultiLink("news", "", "news", "news_add_job"); + $oLnkAddJob->setCustom("idnewsletter", $idnewsletter); + $oLnkAddJob->setAlt($aMsg["AddJobTitle"]); + $oLnkAddJob->setContent('' . $aMsg['); + + $sLnkAddJob = $oLnkAddJob->render(); + } else { + $sLnkAddJob = '' . $aMsg['; + } + + $oMenu->setActions($iMenu, 'dispatch', $sLnkAddJob); + } + + if ($perm->have_perm_area_action($area, "news_create")) { + $oLnkCopy = new Link; + $oLnkCopy->setMultiLink("news", "", "news", "news_duplicate"); + $oLnkCopy->setCustom("idnewsletter", $idnewsletter); + $oLnkCopy->setAlt($aMsg["CopyTitle"]); + $oLnkCopy->setContent('' . $aMsg['); + + $oMenu->setActions($iMenu, 'copy', $oLnkCopy->render()); + } + + if ($perm->have_perm_area_action($area, "news_delete")) { + $sDelete = '' . $aMsg['; + $oMenu->setActions($iMenu, 'delete', $sDelete); + } +} + +// Check destination for sending test newsletter +if ($_REQUEST["selTestDestination"] > 0 && $perm->have_perm_area_action($area, "news_send_test")) { + $oRcpGroups = new RecipientGroupCollection; + $oRcpGroups->setWhere("idclient", $client); + $oRcpGroups->setWhere("idlang", $lang); + $oRcpGroups->setWhere($oRcpGroups->primaryKey, $_REQUEST["selTestDestination"]); + $oRcpGroups->query(); + + if ($oRcpGroup = $oRcpGroups->next()) { + $sSendTestTarget = sprintf(i18n("Recipient group: %s", "cl_newsletter"), $oRcpGroup->get("groupname")); + } + unset($oRcpGroups); +} + +$aMsg["SendTestDescr"] = sprintf(i18n("Do you really want to send the newsletter to:
%s", "cl_newsletter"), $sSendTestTarget); + +$sExecScript = ' + '; + +$oPage->setMargin(0); + +// Messagebox JS has to be included before ExecScript! +$oPage->addScript('messagebox', ''); +$oPage->addScript('exec', $sExecScript); +$oPage->addScript('parameterCollector.js', ''); + +// Generate current content for Object Pager +$sPagerId = "0ed6d632-6adf-4f09-a0c6-1e38ab60e302"; +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("elemperpage", $_REQUEST["elemperpage"]); +$oPagerLink->setCustom("filter", $_REQUEST["filter"]); +$oPagerLink->setCustom("restrictgroup", $_REQUEST["restrictgroup"]); +$oPagerLink->setCustom("sortby", $_REQUEST["sortby"]); +$oPagerLink->setCustom("sortorder", $_REQUEST["sortorder"]); +$oPagerLink->setCustom("searchin", $_REQUEST["searchin"]); +$oPagerLink->setCustom("restrictgroup", $_REQUEST["restrictgroup"]); +$oPagerLink->setCustom("frame", 2); +$oPagerLink->setCustom("area", $area); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); +// Note, that after the "page" parameter no "pagerlink" parameter is specified - +// it is not used, as the JS below only uses the INNER html and the "pagerlink" parameter is +// set by ...left_top.html for the foldingrow itself +$oPager = new cObjectPager($sPagerId, $iItemCount, $_REQUEST["elemperpage"], $_REQUEST["page"], $oPagerLink, "page"); + +// Add slashes, to insert in javascript +$sPagerContent = $oPager->render(1); +$sPagerContent = str_replace('\\', '\\\\', $sPagerContent); +$sPagerContent = str_replace('\'', '\\\'', $sPagerContent); + +// Send new object pager to left_top +$oPage->addScript('setpager', ''); + +$sRefreshPager = ' + '; + +$oPage->addScript('refreshpager', $sRefreshPager); + +$oPage->setContent($oMenu->render(false)); +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.newsletter_subnav.php b/includes/include.newsletter_subnav.php new file mode 100644 index 0000000..6f4dc75 --- /dev/null +++ b/includes/include.newsletter_subnav.php @@ -0,0 +1,65 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * modified 2010-05-20, Murat Purc, removed request check during processing ticket [#CON-307] + * + * $Id: include.newsletter_subnav.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ + +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +if (isset($_GET['idnewsletter'])) +{ + # Set template data + $sCaption = i18n("Edit", "cl_newsletter"); + + $tpl->set("d", "ID", 'c_'.$tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", ''.$sCaption.''); + $tpl->next(); + + # Set template data + $sCaption = i18n("Edit Message", "cl_newsletter"); + + $tpl->set("d", "ID", 'c_'.$tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", ''.$sCaption.''); + $tpl->next(); + + $tpl->set('s', 'COLSPAN', ($tpl->dyn_cnt * 2) + 2); + + # Generate the third navigation layer + $tpl->generate($cfg["path"]["templates"] . $cfg["templates"]["subnav"]); +} else { + include ($cfg["path"]["contenido"].$cfg["path"]["templates"] . $cfg["templates"]["right_top_blank"]); +} + +?> \ No newline at end of file diff --git a/includes/include.recipients.group.subnav.php b/includes/include.recipients.group.subnav.php new file mode 100644 index 0000000..9173df5 --- /dev/null +++ b/includes/include.recipients.group.subnav.php @@ -0,0 +1,72 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * modified 2010-05-20, Murat Purc, removed request check during processing ticket [#CON-307] + * + * $Id: include.recipients.group.subnav.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +if (isset($_GET['idrecipientgroup']) && (int) $_GET['idrecipientgroup'] > 0) { + $caption = i18n("Overview", "cl_newsletter"); + $tmp_area = "foo2"; + + # Set template data + $tpl->set("d", "ID", 'c_' . $tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", '' . $caption . ''); + $tpl->next(); + + if (is_array($cfg['plugins']['recipientslogic'])) { + foreach ($cfg['plugins']['recipientslogic'] as $plugin) { + cInclude("plugins", "recipientslogic/$plugin/" . $plugin . ".php"); + + $className = "recipientslogic_" . $plugin; + $class = new $className; + + $caption = $class->getFriendlyName(); + $tmp_area = "foo2"; + $tpl->set("d", "ID", 'c_' . $tpl->dyn_cnt); + $tpl->set("d", "CLASS", ''); + $tpl->set("d", "OPTIONS", ''); + $tpl->set("d", "CAPTION", '' . $caption . ''); + $tpl->next(); + } + } + + $tpl->set('s', 'COLSPAN', ($tpl->dyn_cnt * 2) + 2); + + # Generate the third navigation layer + $tpl->generate($cfg["path"]["templates"] . $cfg["templates"]["subnav"]); +} else { + include ($cfg["path"]["contenido"] . $cfg["path"]["templates"] . $cfg["templates"]["right_top_blank"]); +} +?> \ No newline at end of file diff --git a/includes/include.recipients.group_edit.php b/includes/include.recipients.group_edit.php new file mode 100644 index 0000000..392002e --- /dev/null +++ b/includes/include.recipients.group_edit.php @@ -0,0 +1,568 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2004-08-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.recipients.group_edit.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +// Initialization +$oPage = new cPage; +$oRGroups = new RecipientGroupCollection; +$oRGroupMembers = new RecipientGroupMemberCollection; +$oRGroup = new RecipientGroup; + +$aFields = array(); +$aFields["name"] = array("field" => "name", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); +$aFields["email"] = array("field" => "email", "caption" => i18n("E-Mail", "cl_newsletter"), "type" => "base,sort,search"); +$aFields["confirmed"] = array("field" => "confirmed", "caption" => i18n("Confirmed", "cl_newsletter"), "type" => "base"); +$aFields["deactivated"] = array("field" => "deactivated", "caption" => i18n("Deactivated", "cl_newsletter"), "type" => "base"); + +if ($action == "recipientgroup_create" && $perm->have_perm_area_action($area, $action)) { + $oRGroup = $oRGroups->create(" " . i18n("-- new group --", "cl_newsletter")); + $_REQUEST["idrecipientgroup"] = $oRGroup->get("idnewsgroup"); + $oPage->setReload(); + $sRefreshLeftTopScript = ''; + $oPage->addScript('refreshlefttop', $sRefreshLeftTopScript); +} elseif ($action == "recipientgroup_delete" && $perm->have_perm_area_action($area, $action)) { + $oRGroups->delete($_REQUEST["idrecipientgroup"]); + $sRefreshLeftTopScript = ''; + $oPage->addScript('refreshlefttop', $sRefreshLeftTopScript); + + $_REQUEST["idrecipientgroup"] = 0; + $oRGroup = new RecipientGroup; + $oPage->setReload(); +} else { + $oRGroup->loadByPrimaryKey($_REQUEST["idrecipientgroup"]); +} + +if ($oRGroup->virgin == false && $oRGroup->get("idclient") == $client && $oRGroup->get("idlang") == $lang) { + if ($action == "recipientgroup_save_group" && $perm->have_perm_area_action($area, $action)) { + // Saving changes + $aMessages = array(); + $bReload = false; + + $sGroupName = stripslashes($_REQUEST["groupname"]); + if ($oRGroup->get("groupname") != $sGroupName) { + $oRGroups->resetQuery(); + $oRGroups->setWhere("groupname", $sGroupName); + $oRGroups->setWhere("idclient", $client); + $oRGroups->setWhere("idlang", $lang); + $oRGroups->setWhere($oRGroup->primaryKey, $oRGroup->get($oRGroup->primaryKey), "!="); + $oRGroups->query(); + + if ($oRGroups->next()) { + $aMessages[] = i18n("Could not set new group name: Group already exists", "cl_newsletter"); + } else { + $bReload = true; + + $oRGroup->set("groupname", $sGroupName); + } + } + + if (count($_REQUEST["adduser"]) > 0) { + foreach ($_REQUEST["adduser"] as $iRcpID) { + if (is_numeric($iRcpID)) { + $oRGroupMembers->create($_REQUEST["idrecipientgroup"], $iRcpID); + } + } + } + + if ($oRGroup->get("defaultgroup") != (int) $_REQUEST["defaultgroup"]) { + $bReload = true; + $oRGroup->set("defaultgroup", $_REQUEST["defaultgroup"]); + } + + $oRGroup->store(); + + if ($bReload) { + $oPage->setReload(); + } + + // Removing users from group (if specified) + //print_r ($_REQUEST["deluser"]); + if ($perm->have_perm_area_action($area, "recipientgroup_recipient_delete") && is_array($_REQUEST["deluser"])) { + foreach ($_REQUEST["deluser"] as $iRcpID) { + if (is_numeric($iRcpID)) { + echo "yo: " . $iRcpID; + $oRGroupMembers->remove($_REQUEST["idrecipientgroup"], $iRcpID); + } + } + } + + $sRefreshLeftTopScript = ''; + $oPage->addScript('refreshlefttop', $sRefreshLeftTopScript); + } + + if (count($aMessages) > 0) { + $sNotis = $notification->returnNotification("warning", implode("
", $aMessages)) . "
"; + } + + // Set default values + $oUser = new cApiUser($auth->auth["uid"]); + if (!isset($_REQUEST["member_elemperpage"]) || !is_numeric($_REQUEST["member_elemperpage"]) || $_REQUEST["member_elemperpage"] < 0) { + $_REQUEST["member_elemperpage"] = $oUser->getProperty("itemsperpage", $area . "_edit_member"); + } + if (!is_numeric($_REQUEST["member_elemperpage"])) { + $_REQUEST["member_elemperpage"] = 25; + } + if ($_REQUEST["member_elemperpage"] > 0) { + // -- All -- will not be stored, as it may be impossible to change this back to something more useful + $oUser->setProperty("itemsperpage", $area . "_edit_member", $_REQUEST["member_elemperpage"]); + } + + if (!isset($_REQUEST["outsider_elemperpage"]) || !is_numeric($_REQUEST["outsider_elemperpage"]) || $_REQUEST["outsider_elemperpage"] < 0) { + $_REQUEST["outsider_elemperpage"] = $oUser->getProperty("itemsperpage", $area . "_edit_outsider"); + } + if (!is_numeric($_REQUEST["outsider_elemperpage"])) { + $_REQUEST["outsider_elemperpage"] = 25; + } + if ($_REQUEST["outsider_elemperpage"] > 0) { + // -- All -- will not be stored, as it may be impossible to change this back to something more useful + $oUser->setProperty("itemsperpage", $area . "_edit_outsider", $_REQUEST["outsider_elemperpage"]); + } + unset($oUser); + + if (!isset($_REQUEST["member_page"]) || !is_numeric($_REQUEST["member_page"]) || $_REQUEST["member_page"] <= 0 || $_REQUEST["member_elemperpage"] == 0) { + $_REQUEST["member_page"] = 1; + } + if ($_REQUEST["member_sortorder"] != "DESC") { + $_REQUEST["member_sortorder"] = "ASC"; + } + if (!isset($_REQUEST["outsider_page"]) || !is_numeric($_REQUEST["outsider_page"]) || $_REQUEST["outsider_page"] <= 0 || $_REQUEST["outsider_elemperpage"] == 0) { + $_REQUEST["outsider_page"] = 1; + } + if ($_REQUEST["outsider_sortorder"] != "DESC") { + $_REQUEST["outsider_sortorder"] = "ASC"; + } + + // Output form + $oForm = new UI_Table_Form("properties", "main.php?1", "get"); // Use "get" for folding rows... + $oForm->setVar("frame", $frame); + $oForm->setVar("area", $area); + $oForm->setVar("action", "recipientgroup_save_group"); + $oForm->setVar("idrecipientgroup", $_REQUEST["idrecipientgroup"]); + $oForm->setSubmitJS("append_registered_parameters(this);"); + + $oForm->addHeader(i18n("Edit group", "cl_newsletter")); + + $oTxtGroupName = new cHTMLTextbox("groupname", $oRGroup->get("groupname"), 40); + $oForm->add(i18n("Group name", "cl_newsletter"), $oTxtGroupName->render()); + + $oCkbDefault = new cHTMLCheckbox("defaultgroup", "1"); + $oCkbDefault->setChecked($oRGroup->get("defaultgroup")); + $oForm->add(i18n("Default group", "cl_newsletter"), $oCkbDefault->toHTML(false)); + + // Member list options folding row + $oMemberListOptionRow = new cFoldingRow("a91f5540-52db-11db-b0de-0800200c9a66", i18n("Member list options", "cl_newsletter")); + + $oSelItemsPerPage = new cHTMLSelectElement("member_elemperpage"); + $oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); + $oSelItemsPerPage->setDefault($_REQUEST["member_elemperpage"]); + + $oSelSortBy = new cHTMLSelectElement("member_sortby"); + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "sort") !== false) { + if ($_REQUEST["member_sortby"] == "") { + $_REQUEST["member_sortby"] = $aData["field"]; + } + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSortBy->addOptionElement($aData["field"], $oOption); + } + } + $oSelSortBy->setDefault($_REQUEST["member_sortby"]); + + $oSelSortOrder = new cHTMLSelectElement("member_sortorder"); + $oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); + $oSelSortOrder->setDefault($_REQUEST["member_sortorder"]); + + $oTxtFilter = new cHTMLTextbox("member_filter", $_REQUEST["member_filter"], 16); + + $oSelSearchIn = new cHTMLSelectElement("member_searchin"); + $oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); + $oSelSearchIn->addOptionElement("all", $oOption); + + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSearchIn->addOptionElement($aData["field"], $oOption); + } + } + $oSelSearchIn->setDefault($_REQUEST["member_searchin"]); + + $oSubmit = new cHTMLButton("submit", i18n("Apply", "cl_newsletter")); + + $sContent = '
' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= '
' . i18n("Items / page", "cl_newsletter") . '' . $oSelItemsPerPage->render() . '
' . i18n("Sort by", "cl_newsletter") . '' . $oSelSortBy->render() . '
' . i18n("Sort order", "cl_newsletter") . '' . $oSelSortOrder->render() . '
' . i18n("Search for", "cl_newsletter") . '' . $oTxtFilter->render() . '
' . i18n("Search in", "cl_newsletter") . '' . $oSelSearchIn->render() . '
 ' . $oSubmit->render() . '
' . chr(10); + $sContent .= '
' . chr(10); + $oMemberListOptionRow->setContentData($sContent); + + // Members + $oAddedRecipientList = new UI_List; + $oAddedRecipientList->setWidth("100%"); + $oAddedRecipientList->setBorder(1); + + $oAddedRecipientList->setCell(0, 1, "" . i18n("Name", "cl_newsletter") . ""); + $oImgDel = new cHTMLImage("images/but_invert_selection.gif"); + $sLnkDelIcon = '' . $oImgDel->render() . ''; + $oAddedRecipientList->setCell(0, 2, $sLnkDelIcon); + $oAddedRecipientList->setCellAlignment(0, 2, "right"); + + $oInsiders = new RecipientCollection; + + $oInsiders->link("RecipientGroupMemberCollection"); + $oInsiders->setWhere("recipientcollection.idclient", $client); + $oInsiders->setWhere("recipientcollection.idlang", $lang); + $oInsiders->setWhere("RecipientGroupMemberCollection.idnewsgroup", $_REQUEST["idrecipientgroup"]); + + // Get insiders for outsiders list (*sigh!*) + // TODO: Ask user to have at least mySQL 4.1... + $oInsiders->query(); + + $aInsiders = array(); + if ($oInsiders->count() > 0) { + while ($oInsider = $oInsiders->next()) { + $aInsiders[] = $oInsider->get($oInsider->primaryKey); + } + } + + // Filter + if ($_REQUEST["member_filter"] != "") { + if ($_REQUEST["member_searchin"] == "--all--" || $_REQUEST["member_searchin"] == "") { + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oInsiders->setWhereGroup("filter", "recipientcollection." . $aData["field"], $_REQUEST["member_filter"], "LIKE"); + } + } + $oInsiders->setInnerGroupCondition("filter", "OR"); + } else { + $oInsiders->setWhere("recipientcollection." . $_REQUEST["member_searchin"], $_REQUEST["member_filter"], "LIKE"); + } + } + + // If elemperpage is something else than "all", get item count based on filters + if ($_REQUEST["member_elemperpage"] > 0) { + $oInsiders->query(); + $iMembers = $oInsiders->count(); // Getting item count without limit (for page function) - better idea anybody (performance)? + + $oInsiders->setLimit($_REQUEST["member_elemperpage"] * ($_REQUEST["member_page"] - 1), $_REQUEST["member_elemperpage"]); + } else { + $iMembers = 0; + } + + // Get data + $sSortSQL = "recipientcollection." . $_REQUEST["member_sortby"] . " " . $_REQUEST["member_sortorder"]; + if ($_REQUEST["member_sortby"] == "name") { + // Name field may be empty, add email as sort criteria + $sSortSQL .= ", email " . $_REQUEST["member_sortorder"]; + } + + $oInsiders->setOrder($sSortSQL); + $oInsiders->query(); + + $iItems = $oInsiders->count(); + if ($iItems == 0 && $_REQUEST["member_filter"] == "" && ($_REQUEST["member_elemperpage"] == 0 || $iMembers == 0)) { + $oAddedRecipientList->setCell(1, 1, i18n("No recipients are added to this group yet", "cl_newsletter")); + $oAddedRecipientList->setCell(1, 2, ' '); + } else if ($iItems == 0) { + $oAddedRecipientList->setCell(1, 1, i18n("No recipients found", "cl_newsletter")); + $oAddedRecipientList->setCell(1, 2, ' '); + } else { + while ($oRcp = $oInsiders->next()) { + $iID = $oRcp->get("idnewsrcp"); + + $sName = $oRcp->get("name"); + $sEMail = $oRcp->get("email"); + if (empty($sName)) { + $sName = $sEMail; + } + $oAddedRecipientList->setCell($iID, 1, $sName . " (" . $sEMail . ")"); + + if ($perm->have_perm_area_action($area, "recipientgroup_recipient_delete")) { + $oCkbDel = new cHTMLCheckbox("deluser[]", $iID); + $oAddedRecipientList->setCell($iID, 2, $oCkbDel->toHTML(false)); + } else { + $oAddedRecipientList->setCell($iID, 2, " "); + } + $oAddedRecipientList->setCellAlignment($iID, 2, "right"); + } + } + + // Member list pager (-> below data, as iMembers is needed) + $oPagerLink = new cHTMLLink; + $oPagerLink->setLink("main.php"); + $oPagerLink->setCustom("member_elemperpage", $_REQUEST["member_elemperpage"]); + $oPagerLink->setCustom("member_filter", $_REQUEST["member_filter"]); + $oPagerLink->setCustom("member_sortby", $_REQUEST["member_sortby"]); + $oPagerLink->setCustom("member_sortorder", $_REQUEST["member_sortorder"]); + $oPagerLink->setCustom("member_searchin", $_REQUEST["member_searchin"]); + $oPagerLink->setCustom("outsider_elemperpage", $_REQUEST["outsider_elemperpage"]); + $oPagerLink->setCustom("outsider_filter", $_REQUEST["outsider_filter"]); + $oPagerLink->setCustom("outsider_sortby", $_REQUEST["outsider_sortby"]); + $oPagerLink->setCustom("outsider_sortorder", $_REQUEST["outsider_sortorder"]); + $oPagerLink->setCustom("outsider_searchin", $_REQUEST["outsider_searchin"]); + $oPagerLink->setCustom("idrecipientgroup", $_REQUEST["idrecipientgroup"]); + $oPagerLink->setCustom("frame", $frame); + $oPagerLink->setCustom("area", $area); + #$oPagerLink->enableAutomaticParameterAppend(); + $oPagerLink->setCustom("contenido", $sess->id); + + $oMemberPager = new cObjectPager("d82a3ff0-52d9-11db-b0de-0800200c9a66", $iMembers, $_REQUEST["member_elemperpage"], $_REQUEST["member_page"], $oPagerLink, "member_page"); + $oMemberPager->setCaption(i18n("Member navigation", "cl_newsletter")); + + $oForm->add(i18n("Recipients in group", "cl_newsletter"), '' . + $oMemberListOptionRow->render() . + $oMemberPager->render() . + '
' . $oAddedRecipientList->render() . '
'); + unset($oInsiders); + unset($oMemberListOptionRow); + unset($oMemberPager); + unset($oAddedRecipientList); + + // Outsiders + // Outsider list options folding row + $oOutsiderListOptionRow = new cFoldingRow("ca633b00-52e9-11db-b0de-0800200c9a66", i18n("Outsider list options", "cl_newsletter")); + + $oSelItemsPerPage = new cHTMLSelectElement("outsider_elemperpage"); + $oSelItemsPerPage->autoFill(array(0 => i18n("-- All --", "cl_newsletter"), 25 => 25, 50 => 50, 75 => 75, 100 => 100)); + $oSelItemsPerPage->setDefault($_REQUEST["outsider_elemperpage"]); + + $oSelSortBy = new cHTMLSelectElement("outsider_sortby"); + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "sort") !== false) { + if ($_REQUEST["outsider_sortby"] == "") { + $_REQUEST["outsider_sortby"] = $aData["field"]; + } + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSortBy->addOptionElement($aData["field"], $oOption); + } + } + $oSelSortBy->setDefault($_REQUEST["outsider_sortby"]); + + $oSelSortOrder = new cHTMLSelectElement("outsider_sortorder"); + $oSelSortOrder->autoFill(array("ASC" => i18n("Ascending", "cl_newsletter"), "DESC" => i18n("Descending", "cl_newsletter"))); + $oSelSortOrder->setDefault($_REQUEST["outsider_sortorder"]); + + $oTxtFilter = new cHTMLTextbox("outsider_filter", $_REQUEST["outsider_filter"], 16); + + $oSelSearchIn = new cHTMLSelectElement("outsider_searchin"); + $oOption = new cHTMLOptionElement(i18n("-- All fields --", "cl_newsletter"), "--all--"); + $oSelSearchIn->addOptionElement("all", $oOption); + + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oOption = new cHTMLOptionElement($aData["caption"], $aData["field"]); + $oSelSearchIn->addOptionElement($aData["field"], $oOption); + } + } + $oSelSearchIn->setDefault($_REQUEST["outsider_searchin"]); + + $oSubmit = new cHTMLButton("submit", i18n("Apply", "cl_newsletter")); + + $sContent = '
' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= ' ' . chr(10); + $sContent .= '
' . i18n("Items / page", "cl_newsletter") . '' . $oSelItemsPerPage->render() . '
' . i18n("Sort by", "cl_newsletter") . '' . $oSelSortBy->render() . '
' . i18n("Sort order", "cl_newsletter") . '' . $oSelSortOrder->render() . '
' . i18n("Search for", "cl_newsletter") . '' . $oTxtFilter->render() . '
' . i18n("Search in", "cl_newsletter") . '' . $oSelSearchIn->render() . '
 ' . $oSubmit->render() . '
' . chr(10); + $sContent .= '
' . chr(10); + $oOutsiderListOptionRow->setContentData($sContent); + + // TODO: Try to enhance genericdb to get this working with the usual objects... + $oOutsiders = new RecipientCollection; + + # This requires mySQL V4.1, at least... + # TODO: Add mySQL server version switch + #$sSQL = "idclient = '".$client."' AND idlang = '".$lang."' AND ". + # "idnewsrcp NOT IN (SELECT idnewsrcp FROM ".$cfg["tab"]["news_groupmembers"]." WHERE idnewsgroup = '".$_REQUEST["idrecipientgroup"]."')"; + // TODO: This works with every mySQL version but may be problematic, if a group + // contains a lot of members (e.g. Oracle can't handle more than 1000 items in the brackets) + $sSQL = "idclient = '" . $client . "' AND idlang = '" . $lang . "' AND " . + "idnewsrcp NOT IN ('" . implode("','", $aInsiders) . "')"; + + if ($_REQUEST["outsider_filter"] != "") { + $sSQLSearchIn = ""; + if ($_REQUEST["outsider_searchin"] == "--all--" || $_REQUEST["outsider_searchin"] == "") { + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + if ($sSQLSearchIn !== "") { + $sSQLSearchIn .= " OR "; + } + $sSQLSearchIn .= $aData["field"] . " LIKE '%" . urlencode($_REQUEST["outsider_filter"]) . "%'"; + } + } + } else { + $sSQLSearchIn .= urlencode($_REQUEST["outsider_searchin"]) . " LIKE '%" . urlencode($_REQUEST["outsider_filter"]) . "%'"; + } + $sSQL .= " AND (" . $sSQLSearchIn . ")"; + } + + // If elemperpage is something else than "all", get item count based on filters + if ($_REQUEST["outsider_elemperpage"] > 0) { + $oOutsiders->flexSelect("", "", $sSQL, ""); + $iOutsiders = $oOutsiders->count(); // Getting item count without limit (for page function) - better idea anyone (performance)? + + $sSQLLimit = " LIMIT " . $_REQUEST["outsider_elemperpage"] * ($_REQUEST["outsider_page"] - 1) . ", " . $_REQUEST["outsider_elemperpage"]; + } else { + $iMembers = 0; + $sSQLLimit = ""; + } + + // Get data + $sSQLSort = " ORDER BY " . urlencode($_REQUEST["outsider_sortby"]) . " " . $_REQUEST["outsider_sortorder"]; + if ($_REQUEST["outsider_sortby"] == "name") { + // Name field may be empty, add email as sort criteria + $sSQLSort .= ", email " . $_REQUEST["outsider_sortorder"]; + } + + $sSQL .= $sSQLSort . $sSQLLimit; + $oOutsiders->flexSelect("", "", $sSQL, ""); + + $aItems = array(); + while ($oRecipient = $oOutsiders->next()) { + $sName = $oRecipient->get("name"); + $sEMail = $oRecipient->get("email"); + + if (empty($sName)) { + $sName = $sEMail; + } + $aItems[] = array($oRecipient->get("idnewsrcp"), $sName . " (" . $sEMail . ")"); + } + + $oSelUser = new cHTMLSelectElement("adduser[]"); + $oSelUser->setSize(25); + $oSelUser->setStyle("width: 100%;"); + $oSelUser->setMultiSelect(); + $oSelUser->autoFill($aItems); + + // Outsider list pager (-> below data, as iOutsiders is needed) + $oPagerLink = new cHTMLLink; + $oPagerLink->setLink("main.php"); + $oPagerLink->setCustom("member_elemperpage", $_REQUEST["member_elemperpage"]); + $oPagerLink->setCustom("member_filter", $_REQUEST["member_filter"]); + $oPagerLink->setCustom("member_sortby", $_REQUEST["member_sortby"]); + $oPagerLink->setCustom("member_sortorder", $_REQUEST["member_sortorder"]); + $oPagerLink->setCustom("member_searchin", $_REQUEST["member_searchin"]); + $oPagerLink->setCustom("outsider_elemperpage", $_REQUEST["outsider_elemperpage"]); + $oPagerLink->setCustom("outsider_filter", $_REQUEST["outsider_filter"]); + $oPagerLink->setCustom("outsider_sortby", $_REQUEST["outsider_sortby"]); + $oPagerLink->setCustom("outsider_sortorder", $_REQUEST["outsider_sortorder"]); + $oPagerLink->setCustom("outsider_searchin", $_REQUEST["outsider_searchin"]); + $oPagerLink->setCustom("idrecipientgroup", $_REQUEST["idrecipientgroup"]); + $oPagerLink->setCustom("frame", $frame); + $oPagerLink->setCustom("area", $area); + #$oPagerLink->enableAutomaticParameterAppend(); + $oPagerLink->setCustom("contenido", $sess->id); + + $oOutsiderPager = new cObjectPager("4d3a7330-52eb-11db-b0de-0800200c9a66", $iOutsiders, $_REQUEST["outsider_elemperpage"], $_REQUEST["outsider_page"], $oPagerLink, "outsider_page"); + $oOutsiderPager->setCaption(i18n("Outsider navigation", "cl_newsletter")); + + $oForm->add(i18n("Add recipients", "cl_newsletter"), '' . + $oOutsiderListOptionRow->render() . + $oOutsiderPager->render() . + '
' . $oSelUser->render() . '
' . i18n("Note: Hold <Ctrl> to
select multiple items.", "cl_newsletter") . '
'); + unset($oOutsiders); + unset($oOutsiderListOptionRow); + unset($oOutsiderPager); + + $sDelMarkScript = ' '; + + $oPage->addScript('DelMarkScript', $sDelMarkScript); + $oPage->addScript('cfoldingrow.js', ''); + $oPage->addScript('parameterCollector.js', ''); + + $oPage->setContent($sNotis . $oForm->render(true)); +} else { + $oPage->setContent($sNotis . ""); +} +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.recipients.group_menu.php b/includes/include.recipients.group_menu.php new file mode 100644 index 0000000..482a0ad --- /dev/null +++ b/includes/include.recipients.group_menu.php @@ -0,0 +1,234 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.recipients.group_menu.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +################################## +# Initialization +################################## +$oPage = new cPage; +$oMenu = new UI_Menu; +$oUser = new cApiUser($auth->auth["uid"]); + +// Specify fields for search, sort and validation. Design makes enhancements +// using plugins possible (currently not implemented). If you are changing things here, +// remember to update include.newsletter_left_top.php, also. +// field: Field name in the db +// caption: Shown field name (-> user) +// base: Elements from core code (other type may be: "plugin") +// sort: Element can be used to be sorted by +// search: Element can be used to search in +$aFields = array(); +$aFields["name"] = array("field" => "groupname", "caption" => i18n("Name", "cl_newsletter"), "type" => "base,sort,search"); + +################################## +# Check external input +################################## +// Items per page (value stored per area in user property) +if (!isset($_REQUEST["elemperpage"]) || !is_numeric($_REQUEST["elemperpage"]) || $_REQUEST["elemperpage"] < 0) { + $_REQUEST["elemperpage"] = $oUser->getProperty("itemsperpage", $area); +} +if (!is_numeric($_REQUEST["elemperpage"])) { + // This is the case, if the user property has never been set (first time user) + $_REQUEST["elemperpage"] = 25; +} +if ($_REQUEST["elemperpage"] > 0) { + // -- All -- will not be stored, as it may be impossible to change this back to something more useful + $oUser->setProperty("itemsperpage", $area, $_REQUEST["elemperpage"]); +} +$_REQUEST["page"] = (int) $_REQUEST["page"]; +if ($_REQUEST["page"] <= 0 || $_REQUEST["elemperpage"] == 0) { + $_REQUEST["page"] = 1; +} +// Sort order +if ($_REQUEST["sortorder"] != "DESC") { + $_REQUEST["sortorder"] = "ASC"; +} + +// Don't need to check sort by and search in criteria - just set it +$_REQUEST["sortby"] = "groupname"; // Default sort by field, possible values see above +$_REQUEST["searchin"] = "--all--"; + +// Free memory +unset($oUser); +unset($oClient); + +################################## +# Get data +################################## +$oRcpGroups = new RecipientGroupCollection; +$oRcpGroups->setWhere("idclient", $client); +$oRcpGroups->setWhere("idlang", $lang); + +if ($_REQUEST["filter"] != "") { + if ($_REQUEST["searchin"] == "--all--" || $_REQUEST["searchin"] == "") { + foreach ($aFields as $sKey => $aData) { + if (strpos($aData["type"], "search") !== false) { + $oRcpGroups->setWhereGroup("filter", $aData["field"], $_REQUEST["filter"], "LIKE"); + } + } + $oRcpGroups->setInnerGroupCondition("filter", "OR"); + } else { + $oRcpGroups->setWhere($_REQUEST["searchin"], $_REQUEST["filter"], "LIKE"); + } +} + +if ($_REQUEST["elemperpage"] > 0) { + // Getting item count without limit (for page function) - better idea anyone (performance)? + $oRcpGroups->query(); + $iItemCount = $oRcpGroups->count(); + + if ($_REQUEST["elemperpage"] * ($_REQUEST["page"]) >= $iItemCount + $_REQUEST["elemperpage"] && $_REQUEST["page"] != 1) { + $_REQUEST["page"] --; + } + + $oRcpGroups->setLimit($_REQUEST["elemperpage"] * ($_REQUEST["page"] - 1), $_REQUEST["elemperpage"]); +} else { + $iItemCount = 0; +} + +$oRcpGroups->setOrder("defaultgroup DESC, " . $_REQUEST["sortby"] . " " . $_REQUEST["sortorder"]); +$oRcpGroups->query(); + +// Output data +$oMenu = new UI_Menu; +$iMenu = 0; + +// Store messages for repeated use (speeds performance, as i18n translation is only needed once) +$aMsg = array(); +$aMsg["DelTitle"] = i18n("Delete recipient group", "cl_newsletter"); +$aMsg["DelDescr"] = i18n("Do you really want to delete the following newsletter recipient group:
", "cl_newsletter"); + +while ($oRcpGroup = $oRcpGroups->next()) { + $iMenu++; + $iIDGroup = $oRcpGroup->get("idnewsgroup"); + + $sName = $oRcpGroup->get("groupname"); + if ($oRcpGroup->get("defaultgroup")) { + $sName = $sName . "*"; + } + + // Create the link to show/edit the recipient group + $oLnk = new cHTMLLink; + $oLnk->setMultiLink("recipientgroups", "", "recipientgroups", ""); + $oLnk->setCustom("idrecipientgroup", $iIDGroup); + + #$oMenu->setImage($iMenu, $cfg["path"]["images"] . "groups.gif"); + $oMenu->setTitle($iMenu, $sName); + $oMenu->setLink($iMenu, $oLnk); + + if ($perm->have_perm_area_action($area, recipientgroup_delete)) { + $oMenu->setActions($iMenu, 'delete', '' . $aMsg['); + } +} + +$sExecScript = ' + '; + +$oPage->setMargin(0); +$oPage->addScript('messagebox', ''); +$oPage->addScript('delete', $sExecScript); +//$oPage->addScript('cfoldingrow.js', ''); +$oPage->addScript('parameterCollector.js', ''); + +// Generate current content for Object Pager +$sPagerId = "0ed6d632-6adf-4f09-a0c6-1e38ab60e305"; +$oPagerLink = new cHTMLLink; +$oPagerLink->setLink("main.php"); +$oPagerLink->setTargetFrame('left_bottom'); +$oPagerLink->setCustom("elemperpage", $_REQUEST["elemperpage"]); +$oPagerLink->setCustom("filter", $_REQUEST["filter"]); +$oPagerLink->setCustom("sortby", $_REQUEST["sortby"]); +$oPagerLink->setCustom("sortorder", $_REQUEST["sortorder"]); +$oPagerLink->setCustom("searchin", $_REQUEST["searchin"]); +$oPagerLink->setCustom("frame", $frame); +$oPagerLink->setCustom("area", $area); +$oPagerLink->enableAutomaticParameterAppend(); +$oPagerLink->setCustom("contenido", $sess->id); +// Note, that after the "page" parameter no "pagerlink" parameter is specified - +// it is not used, as the JS below only uses the INNER html and the "pagerlink" parameter is +// set by ...left_top.html for the foldingrow itself +$oPager = new cObjectPager($sPagerId, $iItemCount, $_REQUEST["elemperpage"], $_REQUEST["page"], $oPagerLink, "page"); + +// Add slashes, to insert in javascript +$sPagerContent = $oPager->render(1); +$sPagerContent = str_replace('\\', '\\\\', $sPagerContent); +$sPagerContent = str_replace('\'', '\\\'', $sPagerContent); + +// Send new object pager to left_top +// Send new object pager to left_top +$oPage->addScript('setpager', ''); + +$sRefreshPager = ' + '; + +$oPage->addScript('refreshpager', $sRefreshPager); + +//$oPage->setContent(array('', '
', $oMenu->render(false))); +$oPage->setContent($oMenu->render(false)); +$oPage->render(); +?> \ No newline at end of file diff --git a/includes/include.recipients_edit.php b/includes/include.recipients_edit.php new file mode 100644 index 0000000..c88b5a4 --- /dev/null +++ b/includes/include.recipients_edit.php @@ -0,0 +1,246 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.recipients_edit.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +$oPage = new cPage; +$oRecipients = new RecipientCollection; + +if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $plugin) { + plugin_include("recipients", $plugin . "/" . $plugin . ".php"); + } +} + +// Note, that the object name has to be $recipient for plugins +if ($action == "recipients_create" && $perm->have_perm_area_action($area, $action)) { + $recipient = $oRecipients->create("mail@domain.tld", " " . i18n("-- new recipient --", "cl_newsletter")); + $oPage->setReload(); +} elseif ($action == "recipients_delete" && $perm->have_perm_area_action($area, $action)) { + $oRecipients->delete($idrecipient); + $recipient = new Recipient; + $oPage->setReload(); +} elseif ($action == "recipients_purge" && $perm->have_perm_area_action($area, "recipients_delete")) { + $oClient = new cApiClient($client); + $timeframe = $oClient->getProperty("newsletter", "purgetimeframe"); + if (!$timeframe) { + $timeframe = 30; + } + $purgedrecipients = $oRecipients->purge($timeframe); + /* backslashdollar: There is a problem translating \$ - it is either not recognized or translated correctly (using poEdit) */ + if ($purgedrecipients > 0) { + $sNotis = $notification->messageBox("info", sprintf(str_replace("backslashdollar", "\$", i18n("%1backslashdollard recipients, which hasn't been confirmed since more than %2backslashdollard days has been removed.", "cl_newsletter")), $purgedrecipients, $timeframe), 0); + } else { + $sNotis = $notification->messageBox("info", sprintf(str_replace("backslashdollar", "\$", i18n("There are no recipients, which hasn't been confirmed since more than %2backslashdollard days has been removed.", "cl_newsletter")), 0, $timeframe), 0); + } + + $recipient = new Recipient; + $oPage->setReload(); +} else { + $recipient = new Recipient($idrecipient); +} + +if ($recipient->virgin == false && $recipient->get("idclient") == $client && $recipient->get("idlang") == $lang) { + if ($action == "recipients_save" && $perm->have_perm_area_action($area, $action)) { + $oPage->setReload(); + $aMessages = array(); + + $name = stripslashes($name); + $email = stripslashes($email); + $confirmed = (int) $confirmed; + $deactivated = (int) $deactivated; + $newstype = (int) $newstype; + + $recipient->set("name", $name); + + if (!isValidMail($email)) { + $aMessages[] = i18n("Please specify a valid e-mail address", "cl_newsletter"); + } else { + $email = strtolower($email); // e-mail always in lower case + if ($recipient->get("email") != $email) { + $oRecipients->resetQuery(); + $oRecipients->setWhere("email", $email); + $oRecipients->setWhere("idclient", $client); + $oRecipients->setWhere("idlang", $lang); + $oRecipients->setWhere($recipient->primaryKey, $recipient->get($recipient->primaryKey), "!="); + $oRecipients->query(); + + if ($oRecipients->next()) { + $aMessages[] = i18n("Could not set new e-mail adress: Other recipient with same e-mail address already exists", "cl_newsletter"); + } else { + $recipient->set("email", $email); + } + } + } + + if ($recipient->get("confirmed") != $confirmed && $confirmed) { + $recipient->set("confirmeddate", date("Y-m-d H:i:s"), false); + } elseif (!$confirmed) { + $recipient->set("confirmeddate", "0000-00-00 00:00:00", false); + } + $recipient->set("confirmed", $confirmed); + $recipient->set("deactivated", $deactivated); + $recipient->set("news_type", $newstype); + + // Check out if there are any plugins + if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $plugin) { + if (function_exists("recipients_" . $plugin . "_wantedVariables") && function_exists("recipients_" . $plugin . "_store")) { + $wantVariables = call_user_func("recipients_" . $plugin . "_wantedVariables"); + + if (is_array($wantVariables)) { + $varArray = array(); + + foreach ($wantVariables as $value) { + $varArray[$value] = stripslashes($GLOBALS[$value]); + } + } + $store = call_user_func("recipients_" . $plugin . "_store", $varArray); + } + } + } + + $recipient->store(); + + // Remove group associations + if (isset($_REQUEST["ckbRemove"])) { + $oGroupMembers = new RecipientGroupMemberCollection; + + foreach ($_REQUEST["ckbRemove"] as $iGroupMemberID) { + if (is_numeric($iGroupMemberID)) { + $oGroupMembers->delete($iGroupMemberID); + } + } + } + } + + if (count($aMessages) > 0) { + $sNotis = $notification->returnNotification("warning", implode("
", $aMessages)) . "
"; + } + + $oForm = new UI_Table_Form("properties"); + $oForm->setVar("frame", $frame); + $oForm->setVar("area", $area); + $oForm->setVar("action", "recipients_save"); + $oForm->setVar("idrecipient", $recipient->get("idnewsrcp")); + + $oForm->addHeader(i18n("Edit recipient", "cl_newsletter")); + + $oTxtName = new cHTMLTextbox("name", $recipient->get("name"), 40); + $oTxtEMail = new cHTMLTextbox("email", $recipient->get("email"), 40); + $oCkbConfirmed = new cHTMLCheckbox("confirmed", "1"); + $oCkbConfirmed->setChecked($recipient->get("confirmed")); + $oCkbDeactivated = new cHTMLCheckbox("deactivated", "1"); + $oCkbDeactivated->setChecked($recipient->get("deactivated")); + + $oSelNewsType = new cHTMLSelectElement("newstype"); + $oOption = new cHTMLOptionElement(i18n("Text only", "cl_newsletter"), "0"); + $oSelNewsType->addOptionElement(0, $oOption); + $oOption = new cHTMLOptionElement(i18n("HTML and text", "cl_newsletter"), "1"); + $oSelNewsType->addOptionElement(1, $oOption); + $oSelNewsType->setDefault($recipient->get("news_type")); + + $oForm->add(i18n("Name", "cl_newsletter"), $oTxtName->render()); + $oForm->add(i18n("E-Mail", "cl_newsletter"), $oTxtEMail->render()); + $oForm->add(i18n("Confirmed", "cl_newsletter"), $oCkbConfirmed->toHTML(false) . " (" . $recipient->get("confirmeddate") . ")"); + $oForm->add(i18n("Deactivated", "cl_newsletter"), $oCkbDeactivated->toHTML(false)); + $oForm->add(i18n("Message type", "cl_newsletter"), $oSelNewsType->render()); + + $aPluginOrder = trim_array(explode(",", getSystemProperty("plugin", "recipients-pluginorder"))); + + // Check out if there are any plugins + if (is_array($aPluginOrder)) { + foreach ($aPluginOrder as $sPlugin) { + if (function_exists("recipients_" . $sPlugin . "_getTitle") && + function_exists("recipients_" . $sPlugin . "_display")) { + $aPluginTitle = call_user_func("recipients_" . $sPlugin . "_getTitle"); + $aPluginDisplay = call_user_func("recipients_" . $sPlugin . "_display", $recipient); + + if (is_array($aPluginTitle) && is_array($aPluginDisplay)) { + foreach ($aPluginTitle as $sKey => $sValue) { + $oForm->add($sValue, $aPluginDisplay[$sKey]); + } + } else { + if (is_array($aPluginTitle) || is_array($aPluginDisplay)) { + $oForm->add(i18n("WARNING", "cl_newsletter"), sprintf(i18n("The plugin %s delivered an array for the displayed titles, but did not return an array for the contents.", "cl_newsletter"), $sPlugin)); + } else { + $oForm->add($aPluginTitle, $aPluginDisplay); + } + } + } + } + } + + $oGroupList = new UI_List; + $oGroupList->setWidth("100%"); + $oGroupList->setBorder(1); + + $oAssocGroups = new RecipientGroupMemberCollection; + $oAssocGroups->link("RecipientGroupCollection"); + $oAssocGroups->setWhere("recipientgroupmembercollection.idnewsrcp", $recipient->get("idnewsrcp")); + $oAssocGroups->setOrder("recipientgroupcollection.groupname"); + $oAssocGroups->query(); + + if ($oAssocGroups->count() == 0) { + $oGroupList->setCell(0, 1, i18n("Recipient is not member of any group", "cl_newsletter")); + } else { + // Headline + $oGroupList->setCell(0, 1, "" . i18n("Groupname", "cl_newsletter") . ""); + $oImgDel = new cHTMLImage("images/delete.gif"); + $oGroupList->setCell(0, 2, $oImgDel->render()); + $oGroupList->setCellAlignment(0, 2, "right"); + + // Data + while ($oAssocGroup = $oAssocGroups->next()) { + $oGroup = $oAssocGroups->fetchObject("RecipientGroupCollection"); + + $oCkbRemove = new cHTMLCheckbox("ckbRemove[]", $oAssocGroup->get("idnewsgroupmember")); + echo ($oGroup->get("idnewsgroupmember")); + $oGroupList->setCell($oAssocGroup->get("idnewsgroupmember"), 1, $oGroup->get("groupname")); + $oGroupList->setCell($oAssocGroup->get("idnewsgroupmember"), 2, $oCkbRemove->toHTML(false)); + $oGroupList->setCellAlignment($oAssocGroup->get("idnewsgroupmember"), 2, "right"); + } + } + + $oForm->add(i18n("Associated Groups", "cl_newsletter"), $oGroupList->render()); + + $oForm->add(i18n("Author", "cl_newsletter"), $classuser->getUserName($recipient->get("author")) . " (" . $recipient->get("created") . ")"); + $oForm->add(i18n("Last modified by", "cl_newsletter"), $classuser->getUserName($recipient->get("modifiedby")) . " (" . $recipient->get("lastmodified") . ")"); + + $oPage->setContent($sNotis . $oForm->render(true)); +} else { + $oPage->setContent($sNotis . ""); +} + +$oPage->render(); +?> diff --git a/includes/include.recipients_import.php b/includes/include.recipients_import.php new file mode 100644 index 0000000..ec7b37d --- /dev/null +++ b/includes/include.recipients_import.php @@ -0,0 +1,360 @@ + + * @license http://www.contenido.org/license/LIZENZ.txt + * @link http://www.4fb.de + * @link http://www.contenido.org + * @since file available since contenido release <= 4.6 + * + * {@internal + * created 2007-01-01, Bj�rn Behrens (HerrB) + * modified 2008-06-27, Dominik Ziegler, add security fix + * + * $Id: include.recipients_import.php 128 2019-07-03 11:58:28Z oldperl $: + * }} + * + */ +if (!defined('CON_FRAMEWORK')) { + die('Illegal call'); +} + + +$oPage = new cPage; +$oRecipients = new RecipientCollection; + +if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $plugin) { + plugin_include("recipients", $plugin . "/" . $plugin . ".php"); + } +} + +// Check form data +if ($_REQUEST["selDelimiter"] == "") { + $_REQUEST["selDelimiter"] = "tab"; +} + +$aFields = array(); +$aFieldDetails = array(); +$aFields["name"] = strtolower(i18n("Name", "cl_newsletter")); +$aFieldDetails["name"]["fieldtype"] = "field"; // field, plugin or group +$aFieldDetails["name"]["mandatory"] = false; // true or false +$aFieldDetails["name"]["type"] = "string"; // string, boolean or date +$aFieldDetails["name"]["link"] = false; // plugin name for plugins, recipient group id for groups +$aFieldDetails["name"]["col"] = -1; // Stores column index where this field has been found +$aFields["email"] = strtolower(i18n("Mail", "cl_newsletter")); +$aFieldDetails["email"]["fieldtype"] = "field"; +$aFieldDetails["email"]["mandatory"] = true; +$aFieldDetails["email"]["type"] = "string"; +$aFieldDetails["email"]["link"] = false; +$aFieldDetails["email"]["col"] = -1; +$aFields["deactivated"] = strtolower(i18n("Deactivated", "cl_newsletter")); +$aFieldDetails["deactivated"]["fieldtype"] = "field"; +$aFieldDetails["deactivated"]["mandatory"] = false; +$aFieldDetails["deactivated"]["type"] = "boolean"; +$aFieldDetails["deactivated"]["link"] = false; +$aFieldDetails["deactivated"]["col"] = -1; +$aFields["confirmed"] = strtolower(i18n("Confirmed", "cl_newsletter")); +$aFieldDetails["confirmed"]["fieldtype"] = "field"; +$aFieldDetails["confirmed"]["mandatory"] = false; +$aFieldDetails["confirmed"]["type"] = "boolean"; +$aFieldDetails["confirmed"]["link"] = false; +$aFieldDetails["confirmed"]["col"] = -1; +$aFields["confirmeddate"] = strtolower(i18n("Confirmed Date", "cl_newsletter")); +$aFieldDetails["confirmeddate"]["fieldtype"] = "field"; +$aFieldDetails["confirmeddate"]["mandatory"] = false; +$aFieldDetails["confirmeddate"]["type"] = "date"; +$aFieldDetails["confirmeddate"]["link"] = false; +$aFieldDetails["confirmeddate"]["col"] = -1; +$aFields["news_type"] = strtolower(i18n("Message type", "cl_newsletter")); +$aFieldDetails["news_type"]["fieldtype"] = "field"; +$aFieldDetails["news_type"]["mandatory"] = false; +$aFieldDetails["news_type"]["type"] = "boolean"; +$aFieldDetails["news_type"]["link"] = false; +$aFieldDetails["news_type"]["col"] = -1; + +// Check out if there are any plugins +if (is_array($cfg['plugins']['recipients'])) { + foreach ($cfg['plugins']['recipients'] as $sPlugin) { + if (function_exists("recipients_" . $sPlugin . "_wantedVariables") && function_exists("recipients_" . $sPlugin . "_canonicalVariables")) { + $aPluginTitles = call_user_func("recipients_" . $sPlugin . "_canonicalVariables"); + $aPluginFields = call_user_func("recipients_" . $sPlugin . "_wantedVariables"); + foreach ($aPluginFields as $sField) { + //if ($_REQUEST["ckb".$sField]) { + $aFields[$sField] = strtolower(str_replace(" ", "", $aPluginTitles[$sField])); + $aFieldDetails[$sField]["fieldtype"] = "plugin"; + $aFieldDetails[$sField]["mandatory"] = false; + $aFieldDetails[$sField]["type"] = "string"; + $aFieldDetails[$sField]["link"] = $sPlugin; + $aFieldDetails[$sField]["col"] = -1; + //} + } + } + } +} + +// Get groups +$oRcpGroups = new RecipientGroupCollection; +$oRcpGroups->setWhere("idclient", $client); +$oRcpGroups->setWhere("idlang", $lang); +$oRcpGroups->setOrder("groupname"); +$oRcpGroups->query(); + +while ($oRcpGroup = $oRcpGroups->next()) { + $sField = "g" . $oRcpGroup->get($oRcpGroup->primaryKey); + + $sGroupName = $oRcpGroup->get("groupname"); + $sGroupName = str_replace(" ", "", $sGroupName); + $sGroupName = str_replace("\t", "", $sGroupName); + $sGroupName = str_replace("\n", "", $sGroupName); + $sGroupName = str_replace("\r", "", $sGroupName); + $sGroupName = str_replace("\0", "", $sGroupName); + $sGroupName = str_replace("\x0B;", "", $sGroupName); + + // Only PHP5! + //$sGroupName = str_replace(str_split(" \t\n\r\0\x0B;"), "", $oRcpGroup->get("groupname")); + + $aFields[$sField] = strtolower(clHtmlEntities(trim(i18n("Group", "cl_newsletter") . "_" . $sGroupName))); + $aFieldDetails[$sField]["fieldtype"] = "group"; + $aFieldDetails[$sField]["mandatory"] = false; + $aFieldDetails[$sField]["type"] = "string"; + $aFieldDetails[$sField]["link"] = $oRcpGroup->get($oRcpGroup->primaryKey); + $aFieldDetails[$sField]["col"] = -1; +} + +if ($action == "recipients_import_exec" && $perm->have_perm_area_action("recipients", "recipients_create")) { + $_REQUEST["txtData"] = trim(stripslashes($_REQUEST["txtData"])); + + if ($_REQUEST["txtData"]) { + switch ($_REQUEST["selDelimiter"]) { + case "semicolon": + $sDelimiter = ";"; + break; + default: + $sDelimiter = "\t"; //chr(9); + } + + //echo "
".nl2br(stripslashes($_REQUEST["txtData"]))."
"; + $aLines = explode("\n", stripslashes($_REQUEST["txtData"])); + $iAdded = 0; + $iDublettes = 0; + $iInvalid = 0; + $iRow = 0; + $iCol = 0; + $bStop = false; + $sMessage = ""; + $aMessage = array(); + $aInvalidLines = array(); + $oGroupMembers = new RecipientGroupMemberCollection; + + foreach ($aLines as $sLine) { + $iRow++; + + $aParts = explode($sDelimiter, trim($sLine)); + + if ($iRow == 1) { + $aInvalidLines[] = $sLine; + + foreach ($aParts as $sHeader) { + $sKey = array_search(strtolower(clHtmlEntities(trim($sHeader))), $aFields); + if ($sKey === false) { + $aMessage[] = sprintf(i18n("Given column header '%s' unknown, column ignored", "cl_newsletter"), $sHeader); + } else { + $aFieldDetails[$sKey]["col"] = $iCol; + $iCol++; + } + } + foreach ($aFieldDetails as $sKey => $aDetails) { + if ($aDetails["mandatory"] && $aDetails["col"] == -1) { + $aMessage[] = sprintf(i18n("Mandatory column '%s' wasn't found, import stopped", "cl_newsletter"), $aDetails[$sKey]); + $bStop = true; + } + } + if ($bStop) { + exit; + } else { + $_REQUEST["txtData"] = ""; + } + } else { + $sEMail = trim($aParts[$aFieldDetails["email"]["col"]]); + if ($aFieldDetails["name"]["col"] > -1) { + $sName = trim($aParts[$aFieldDetails["name"]["col"]]); + if ($sName == "") { + $sName = $sEMail; + } + } else { + $sName = $sEMail; + } + if ($sEMail == "") { + $aMessage[] = sprintf(i18n("Item with empty mail address found, item ignored (name: %s, row: %s)", "cl_newsletter"), $sName, $iRow); + $aInvalidLines[] = $sLine; + $iInvalid++; + } else if (!isValidMail($sEMail)) { + $aMessage[] = sprintf(i18n("Mail address '%s' is invalid, item ignored (row: %s)", "cl_newsletter"), $sEMail, $iRow); + $aInvalidLines[] = $sLine; + $iInvalid++; + } else if ($oRecipients->emailExists($sEMail)) { + $aMessage[] = sprintf(i18n("Recipient with mail address '%s' already exists, item skipped (row: %s)", "cl_newsletter"), $sEMail, $iRow); + $aInvalidLines[] = $sLine; + $iDublettes++; + } else { + unset($sLine); + + // Must be $recipient for plugins + if ($recipient = $oRecipients->create($sEMail, $sName)) { + $iID = $recipient->get($recipient->primaryKey); + $iAdded++; + + unset($aPluginValue); + $aPluginValue = array(); + + foreach ($aFieldDetails as $sKey => $aDetails) { + if ($aDetails["col"] > -1) { + switch ($aDetails["fieldtype"]) { + case "field": + switch ($aDetails["type"]) { + case "boolean": + $sValue = strtolower(trim($aParts[$aDetails["col"]])); + + // html is only treated as "true", to get html messages for recipients + // - quick and dirty... + if ($sValue == "yes" || $sValue == i18n("yes", "cl_newsletter") || $sValue == "true" || + (is_numeric($sValue) && $sValue > 0) || + $sValue == "html") { + $recipient->set($sKey, 1); + + if ($sKey == "confirmed") { + // Ensure, that if a recipient is confirmed, a confirmed date + // is available. As "confirmeddate" will be set after "confirmed" + // a specified confirmeddate will overwrite this default + $recipient->set("confirmeddate", date("Y-m-d H:i:s"), false); + } + } else { + $recipient->set($sKey, 0); + } + break; + case "date": + // TODO: Check conversion: Result may be unpredictable... + $sValue = trim($aParts[$aDetails["col"]]); + $recipient->set($sKey, date("Y-m-d H:i:s", strtotime($sValue)), false); + break; + default: + $sValue = trim($aParts[$aDetails["col"]]); + $recipient->set($sKey, $sValue); + } + break; + case "plugin": + // type may be mentioned here, also, but as plugins currently can't + // specify the type, just treat everything as string + // There may be plugins which store more than one value per plugin_store- + // function. As the plugin_store parameter is an array of values, collect + // all values in an array for later storing... unfortunately, that means, + // that we have to go through the fields array second time per item *sigh* + $aPluginValue[$aDetails["link"]][$sKey] = trim($aParts[$aDetails["col"]]); + break; + case "group": + // Add recipient to group + $sValue = strtolower(trim($aParts[$aDetails["col"]])); + + if ($sValue == "yes" || $sValue == i18n("yes", "cl_newsletter") || + $sValue == "true" || (is_numeric($sValue) && $sValue > 0)) { + $oGroupMembers->create($aDetails["link"], $iID); + } + break; + } + } + } + // Store all base data + $recipient->store(); + + // Store plugin data (to store plugin data, only, where the column has been found in the data + // should be faster than going through all plugins and store mostly empty arrays) + $sCurrentPlugin = ""; + foreach ($aFieldDetails as $sKey => $aDetails) { + if ($aDetails["col"] > -1 && + $aDetails["fieldtype"] == "plugin" && + $aDetails["link"] !== $sCurrentPlugin) { + $sCurrentPlugin = $aDetails["link"]; + + call_user_func("recipients_" . $sCurrentPlugin . "_store", $aPluginValue[$sCurrentPlugin]); + } + } + } + } + } + } + if (count($aInvalidLines) > 1) { + $_REQUEST["txtData"] = implode("\n", $aInvalidLines); + } + if (count($aMessage) > 0) { + $sMessage = $notification->returnNotification("warning", implode("
", $aMessage)) . "
"; + } + $sMessage .= $notification->returnNotification("info", sprintf(i18n("%d recipients added, %d recipients skipped (email already exists) and %d invalid recipients/e-mail adresses ignored. Invalid recipients are shown (if any).", "cl_newsletter"), $iAdded, $iDublettes, $iInvalid)); + if ($iAdded > 0) { + $oPage->setReload(); + } + } +} + +$oForm = new UI_Table_Form("properties"); +$oForm->setVar("frame", $frame); +$oForm->setVar("area", $area); +$oForm->setVar("action", "recipients_import_exec"); + +$oForm->addHeader(i18n("Import recipients", "cl_newsletter")); + +$oSelDelimiter = new cHTMLSelectElement("selDelimiter"); +$aItems = array(); +$aItems[] = array("tab", i18n("Tab", "cl_newsletter")); +$aItems[] = array("semicolon", i18n("Semicolon", "cl_newsletter")); +$oSelDelimiter->autoFill($aItems); +$oSelDelimiter->setDefault($_REQUEST["selDelimiter"]); +$oForm->add(i18n("Delimiter", "cl_newsletter"), $oSelDelimiter->render()); + +$oAreaData = new cHTMLTextarea("txtData", $_REQUEST["txtData"], 80, 20); + +$sInfo = '' . i18n("Import information", "cl_newsletter") . '' . + '