Attached Files |
engine_for_subscriping_to_system_events.patch [^] (32,190 bytes) 2012-03-30 12:46
[Show Content]
Index: admin/system_presets/simple/email_events_emailevents.php
===================================================================
--- admin/system_presets/simple/email_events_emailevents.php (revision 15222)
+++ admin/system_presets/simple/email_events_emailevents.php (working copy)
@@ -29,7 +29,7 @@
/*'EventId', 'Event', 'ReplacementTags', 'AllowChangingSender', 'CustomSender',
'SenderName', 'SenderAddressType', 'SenderAddress', 'AllowChangingRecipient',
'CustomRecipient', 'Recipients', 'Subject', 'HtmlBody', 'PlainTextBody', 'Headers',
- 'Enabled', 'FrontEndOnly', 'Module', 'Description', 'Type'*/
+ 'Enabled', 'FrontEndOnly', 'Module', 'BindToSystemEvent', 'Description', 'Type'*/
);
// virtual fields to hide
@@ -43,7 +43,7 @@
/*'EventId',*/ 'Event', /*'ReplacementTags', 'AllowChangingSender', 'CustomSender',
'SenderName', 'SenderAddressType', 'SenderAddress', 'AllowChangingRecipient',
'CustomRecipient', 'Recipients',*/ 'Subject', /*'HtmlBody', 'PlainTextBody', 'Headers',*/
- /*'Enabled', 'FrontEndOnly',*/ 'Module', /*'Description',*/ 'Type'
+ /*'Enabled', 'FrontEndOnly',*/ 'Module', /*'BindToSystemEvent', 'Description',*/ 'Type'
);
// virtual fields to make required
Index: core/admin_templates/incs/form_blocks.tpl
===================================================================
--- core/admin_templates/incs/form_blocks.tpl (revision 15165)
+++ core/admin_templates/incs/form_blocks.tpl (working copy)
@@ -682,7 +682,7 @@
</inp2:m_RenderElement>
</inp2:m_DefineElement>
-<inp2:m_DefineElement name="inp_edit_combo_target" caption_render_as="default_field_caption_element" read_only="0" has_empty="" hint_label="">
+<inp2:m_DefineElement name="inp_edit_combo_target" title="la_fld_{$field}" caption_render_as="default_field_caption_element" read_only="0" has_empty="" hint_label="">
<inp2:m_RenderElement design="form_row" pass_params="1">
<td class="control-cell">
<inp2:m_if check="m_Param" name="read_only">
Index: core/admin_templates/languages/email_message_settings.tpl
===================================================================
--- core/admin_templates/languages/email_message_settings.tpl (revision 15222)
+++ core/admin_templates/languages/email_message_settings.tpl (working copy)
@@ -57,51 +57,52 @@
<table class="edit-form">
<inp2:m_RenderElement name="subsection" prefix="emailevents" fields="AllowChangingSender,CustomSender,SenderAddress,SenderAddressType,SenderName" title="la_section_SenderInfo"/>
<inp2:m_if check="m_IsDebugMode">
- <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="AllowChangingSender" title="la_fld_AllowChangingSender"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="AllowChangingSender"/>
</inp2:m_if>
<inp2:m_if check="emailevents_IsEditable" check_field="AllowChangingSender">
- <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="CustomSender" title="la_fld_CustomSender"/>
- <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="SenderAddress" title="la_fld_SenderAddress" has_empty="1"/>
- <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="SenderName" title="la_fld_SenderName" style="width: 318px;"/>
+ <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="CustomSender"/>
+ <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="SenderAddress" has_empty="1"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="SenderName" style="width: 318px;"/>
<inp2:m_else/>
- <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="CustomSender" title="la_fld_CustomSender"/>
- <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="SenderAddress" title="la_fld_SenderAddress" read_only="1"/>
- <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="SenderName" title="la_fld_SenderName"/>
+ <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="CustomSender"/>
+ <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="SenderAddress" read_only="1"/>
+ <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="SenderName"/>
</inp2:m_if>
<inp2:m_RenderElement name="subsection" prefix="emailevents" fields="AllowChangingRecipient,CustomRecipient,RecipientType,RecipientAddress,RecipientAddressType,RecipientName,Recipients" title="la_section_RecipientsInfo"/>
<inp2:m_if check="m_IsDebugMode">
- <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="AllowChangingRecipient" title="la_fld_AllowChangingRecipient"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="AllowChangingRecipient"/>
</inp2:m_if>
<inp2:m_if check="emailevents_IsEditable" check_field="AllowChangingRecipient">
- <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="CustomRecipient" title="la_fld_CustomRecipient"/>
+ <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="CustomRecipient"/>
<inp2:m_else/>
- <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="CustomRecipient" title="la_fld_CustomRecipient"/>
+ <inp2:m_RenderElement name="inp_label" prefix="emailevents" field="CustomRecipient"/>
<inp2:emailevents_RemoveToRecipientType/>
</inp2:m_if>
- <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="RecipientType" title="la_fld_RecipientType"/>
- <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="RecipientAddress" title="la_fld_RecipientAddress" has_empty="1"/>
- <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="RecipientName" title="la_fld_RecipientName" style="width: 318px;"/>
- <inp2:m_RenderElement name="inp_edit_minput" prefix="emailevents" field="Recipients" title="la_fld_Recipients" format="auto" style="width: 400px; height: 150px;"/>
+ <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="RecipientType"/>
+ <inp2:m_RenderElement name="inp_edit_combo_target" prefix="emailevents" field="RecipientAddress" has_empty="1"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="RecipientName" style="width: 318px;"/>
+ <inp2:m_RenderElement name="inp_edit_minput" prefix="emailevents" field="Recipients" format="auto" style="width: 400px; height: 150px;"/>
<inp2:m_RenderElement name="subsection" prefix="emailevents" fields="Tag,Replacement,ReplacementTagsXML" title="la_section_ReplacementTags"/>
- <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="Tag" title="la_fld_Tag"/>
- <inp2:m_RenderElement name="inp_edit_textarea" prefix="emailevents" field="Replacement" title="la_fld_Replacement"control_options="{height: 60}"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="Tag"/>
+ <inp2:m_RenderElement name="inp_edit_textarea" prefix="emailevents" field="Replacement" control_options="{height: 60}"/>
<inp2:m_RenderElement name="inp_edit_minput" prefix="emailevents" field="ReplacementTagsXML" title="la_fld_ReplacementTags" allow_move="0" format="#Tag# = #Replacement#" style="width: 600px; height: 100px;"/>
- <inp2:m_RenderElement name="subsection" prefix="emailevents" fields="Enabled,Description,FrontEndOnly,Type,Headers,Module" title="la_section_General"/>
+ <inp2:m_RenderElement name="subsection" prefix="emailevents" fields="Enabled,Description,FrontEndOnly,Type,Headers,Module,BindToSystemEvent" title="la_section_General"/>
<inp2:m_if check="m_IsDebugMode">
- <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="Enabled" title="la_fld_Enabled"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="Enabled"/>
</inp2:m_if>
- <inp2:m_RenderElement name="inp_edit_textarea" prefix="emailevents" field="Description" title="la_fld_Description" control_options="{max_height: 50}"/>
- <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="FrontEndOnly" title="la_fld_FrontEndOnly"/>
- <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="Type" title="la_fld_Type"/>
+ <inp2:m_RenderElement name="inp_edit_textarea" prefix="emailevents" field="Description" control_options="{max_height: 50}"/>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="emailevents" field="FrontEndOnly"/>
+ <inp2:m_RenderElement name="inp_edit_radio" prefix="emailevents" field="Type"/>
<inp2:m_RenderElement name="inp_edit_textarea" prefix="emailevents" field="Headers" title="la_fld_ExtraHeaders" control_options="{max_height: 50}"/>
- <inp2:m_RenderElement name="inp_edit_options" prefix="emailevents" field="Module" title="la_fld_Module" has_empty="1"/>
+ <inp2:m_RenderElement name="inp_edit_options" prefix="emailevents" field="Module" has_empty="1"/>
+ <inp2:m_RenderElement name="inp_edit_box" prefix="emailevents" field="BindToSystemEvent" style="width: 200px;"/>
<inp2:m_RenderElement name="inp_edit_filler"/>
</table>
</div>
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql (revision 15246)
+++ core/install/install_schema.sql (working copy)
@@ -117,6 +117,7 @@
Description text,
`Type` int(11) NOT NULL DEFAULT '0',
LastChanged int(10) unsigned DEFAULT NULL,
+ BindToSystemEvent varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (EventId),
KEY `Type` (`Type`),
KEY Enabled (Enabled),
@@ -139,6 +140,19 @@
KEY l5_PlainTextBody (l5_PlainTextBody(5))
);
+CREATE TABLE EmailEventSubscribers (
+ SubscriptionId int(11) NOT NULL AUTO_INCREMENT,
+ EmailEventId int(11) DEFAULT NULL,
+ SubscriberEmail varchar(255) NOT NULL DEFAULT '',
+ UserId int(11) DEFAULT NULL,
+ CategoryId int(11) DEFAULT NULL,
+ ItemId int(11) DEFAULT NULL,
+ ParentItemId int(11) DEFAULT NULL,
+ SubscribedOn int(11) DEFAULT NULL,
+ PRIMARY KEY (SubscriptionId),
+ KEY EmailEventId (EmailEventId)
+);
+
CREATE TABLE IdGenerator (
lastid int(11) default NULL
);
Index: core/install/remove_schema.sql
===================================================================
--- core/install/remove_schema.sql (revision 15165)
+++ core/install/remove_schema.sql (working copy)
@@ -4,6 +4,7 @@
DROP TABLE SystemSettings;
DROP TABLE EmailQueue;
DROP TABLE EmailEvents;
+DROP TABLE EmailEventSubscribers;
DROP TABLE IdGenerator;
DROP TABLE Languages;
DROP TABLE Modules;
Index: core/kernel/application.php
===================================================================
--- core/kernel/application.php (revision 15251)
+++ core/kernel/application.php (working copy)
@@ -2024,6 +2024,7 @@
* @param kEvent $event
* @param Array $params
* @param Array $specific_params
+ * @return void
* @access public
*/
public function HandleEvent($event, $params = null, $specific_params = null)
@@ -2036,6 +2037,17 @@
}
/**
+ * Notifies event subscribers, that event has occured
+ *
+ * @param kEvent $event
+ * @return void
+ */
+ public function notifyEventSubscribers(kEvent $event)
+ {
+ $this->EventManager->notifySubscribers($event);
+ }
+
+ /**
* Allows to process any type of event
*
* @param kEvent $event
@@ -2430,6 +2442,12 @@
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
+ if ( $exception instanceof kRedirectException ) {
+ /* @var $exception kRedirectException */
+
+ $exception->run();
+ }
+
if ( !$this->exceptionHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
$this->errorDisplayFatal('<strong>' . get_class($exception) . ': </strong>' . "{$errstr} in {$errfile} on line {$errline}");
Index: core/kernel/db/db_event_handler.php
===================================================================
--- core/kernel/db/db_event_handler.php (revision 15226)
+++ core/kernel/db/db_event_handler.php (working copy)
@@ -581,6 +581,7 @@
$user_id = $this->Application->InitDone ? $this->Application->RecallVar('user_id') : USER_ROOT;
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
$status_checked = false;
+
if ( $user_id == USER_ROOT || $this->CheckPermission($event) ) {
// don't autoload item, when user doesn't have view permission
$this->LoadItem($event);
@@ -599,29 +600,7 @@
if ( !$perm_status ) {
// when no permission to view item -> redirect to no permission template
- if ( $this->Application->isDebugMode() ) {
- $this->Application->Debugger->appendTrace();
- }
-
- trigger_error('ItemLoad Permission Failed for prefix [' . $event->getPrefixSpecial() . '] in <strong>' . ($status_checked ? 'checkItemStatus' : 'CheckPermission') . '</strong>', E_USER_NOTICE);
- $template = $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
-
- if ( $this->Application->GetVar('t') != $template ) {
- // don't perform "no_permission" redirect if already on a "no_permission" template
- if ( MOD_REWRITE ) {
- $redirect_params = Array (
- 'm_cat_id' => 0,
- 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']),
- );
- }
- else {
- $redirect_params = Array (
- 'next_template' => $this->Application->GetVar('t'),
- );
- }
-
- $this->Application->Redirect($template, $redirect_params);
- }
+ $this->_processItemLoadingError($event, $status_checked);
}
}
@@ -634,6 +613,50 @@
}
/**
+ * Processes case, when item wasn't loaded because of lack of permissions
+ *
+ * @param kEvent $event
+ * @param bool $status_checked
+ * @throws kNoPermissionException
+ * @return void
+ * @access protected
+ */
+ protected function _processItemLoadingError($event, $status_checked)
+ {
+ $current_template = $this->Application->GetVar('t');
+ $redirect_template = $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
+ $error_msg = 'ItemLoad Permission Failed for prefix [' . $event->getPrefixSpecial() . '] in <strong>' . ($status_checked ? 'checkItemStatus' : 'CheckPermission') . '</strong>';
+
+ if ( $current_template == $redirect_template ) {
+ // don't perform "no_permission" redirect if already on a "no_permission" template
+ if ( $this->Application->isDebugMode() ) {
+ $this->Application->Debugger->appendTrace();
+ }
+
+ trigger_error($error_msg, E_USER_NOTICE);
+
+ return;
+ }
+
+ if ( MOD_REWRITE ) {
+ $redirect_params = Array (
+ 'm_cat_id' => 0,
+ 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']),
+ );
+ }
+ else {
+ $redirect_params = Array (
+ 'next_template' => $current_template,
+ );
+ }
+
+ $exception = new kNoPermissionException($error_msg);
+ $exception->setup($redirect_template, $redirect_params);
+
+ throw $exception;
+ }
+
+ /**
* Build sub-tables array from configs
*
* @param kEvent $event
@@ -2412,13 +2435,28 @@
* Occurs after deleting item, id of deleted item
* is stored as 'id' param of event
*
+ * Also deletes subscriptions to that particual item once it's deleted
+ *
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemDelete(kEvent $event)
{
+ $object = $event->getObject();
+ /* @var $object kDBItem */
+ $sql = 'SELECT EventId
+ FROM ' . TABLE_PREFIX . 'EmailEvents
+ WHERE BindToSystemEvent REGEXP "' . $this->Conn->escape($event->Prefix) . '[.]{0,1}([^:]*):(.*)"';
+ $email_event_ids = $this->Conn->GetCol($sql);
+
+ if ( $email_event_ids ) {
+ // e-mail events, connected to that unit prefix are found
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'EmailEventSubscribers
+ WHERE ItemId = ' . $object->GetID() . ' AND EmailEventId IN (' . implode(',', $email_event_ids) . ')';
+ $this->Conn->Query($sql);
+ }
}
/**
Index: core/kernel/db/dbitem.php
===================================================================
--- core/kernel/db/dbitem.php (revision 15226)
+++ core/kernel/db/dbitem.php (working copy)
@@ -372,14 +372,14 @@
}
/**
- * Loads item from the database by given id
- *
- * @access public
- * @param mixed $id item id of keys->values hash to load item by
- * @param string $id_field_name Optional parameter to load item by given Id field
- * @param bool $cachable cache this query result based on it's prefix serial
- * @return bool True if item has been loaded, false otherwise
- */
+ * Loads item from the database by given id
+ *
+ * @access public
+ * @param mixed $id item id of keys->values hash to load item by
+ * @param string $id_field_name Optional parameter to load item by given Id field
+ * @param bool $cachable cache this query result based on it's prefix serial
+ * @return bool True if item has been loaded, false otherwise
+ */
public function Load($id, $id_field_name = null, $cachable = false)
{
if ( isset($id_field_name) ) {
@@ -1154,8 +1154,9 @@
* @param string $parent_prefix
* @param bool $top_most return topmost parent, when used
* @return int
+ * @access public
*/
- protected function getParentId($parent_prefix, $top_most = false)
+ public function getParentId($parent_prefix, $top_most = false)
{
$current_id = $this->GetID();
$current_prefix = $this->Prefix;
Index: core/kernel/event_handler.php
===================================================================
--- core/kernel/event_handler.php (revision 15250)
+++ core/kernel/event_handler.php (working copy)
@@ -209,4 +209,19 @@
}
+ /**
+ * Returns sql query to be used for event subscriber list selection
+ *
+ * @param kEvent $event
+ * @return string
+ * @access protected
+ */
+ protected function OnGetEventSubscribersQuery(kEvent $event)
+ {
+ $sql = 'SELECT SubscriberEmail, UserId
+ FROM ' . TABLE_PREFIX . 'EmailEventSubscribers
+ WHERE (' . implode(') AND (', $event->getEventParam('where_clause')) . ')';
+ $event->setEventParam('sql', $sql);
+ }
+
}
\ No newline at end of file
Index: core/kernel/event_manager.php
===================================================================
--- core/kernel/event_manager.php (revision 15250)
+++ core/kernel/event_manager.php (working copy)
@@ -237,6 +237,7 @@
* Allows to process any type of event
*
* @param kEvent $event
+ * @return void
* @access public
*/
public function HandleEvent($event)
@@ -272,6 +273,136 @@
}
/**
+ * Notifies event subscribers, that event has occured
+ *
+ * @param kEvent $event
+ * @return void
+ */
+ public function notifySubscribers(kEvent $event)
+ {
+ if ( $event->status != kEvent::erSUCCESS ) {
+ return;
+ }
+
+ $cache_key = 'email_to_event_mapping[%EmaileventsSerial%]';
+ $event_mapping = $this->Application->getCache($cache_key);
+
+ if ( $event_mapping === false ) {
+ $this->Conn->nextQueryCachable = true;
+ $sql = 'SELECT EventId, Event, Type, BindToSystemEvent
+ FROM ' . TABLE_PREFIX . 'EmailEvents
+ WHERE BindToSystemEvent <> ""';
+ $event_mapping = $this->Conn->Query($sql, 'BindToSystemEvent');
+
+ $this->Application->setCache($cache_key, $event_mapping);
+ }
+
+ $email_event = Array ();
+
+ if ( isset($event_mapping[(string)$event]) ) {
+ $email_event = $event_mapping[(string)$event];
+ }
+ elseif ( isset($event_mapping[$event->Prefix . '.*:' . $event->Name]) ) {
+ $email_event = $event_mapping[$event->Prefix . '.*:' . $event->Name];
+ }
+
+ if ( !$email_event ) {
+ return;
+ }
+
+ $category_ids = $item_id = $parent_item_id = false;
+ $where_clause = Array ();
+ $where_clause['EmailEventId'] = 'EmailEventId = ' . $email_event['EventId'];
+
+ try {
+ $category = $this->Application->recallObject('c');
+ /* @var $category kDBItem */
+
+ if ( $category->isLoaded() ) {
+ $category_ids = trim(str_replace('|', ',', $category->GetDBField('ParentPath')), ',');
+ }
+ }
+ catch (Exception $e) {
+ }
+
+ $where_clause['CategoryId'] = $this->_getSubscriberFilter('CategoryId', $category_ids, true);
+
+ try {
+ $object = $event->getObject();
+ /* @var $object kDBItem */
+
+ if ( $object->isLoaded() ) {
+ $item_id = $object->GetID();
+ $parent_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
+
+ if ( $parent_prefix ) {
+ $parent_item_id = $object->getParentId($parent_prefix);
+ }
+ }
+ }
+ catch (Exception $e) {
+ }
+
+ $where_clause['ItemId'] = $this->_getSubscriberFilter('ItemId', $item_id);
+ $where_clause['ParentItemId'] = $this->_getSubscriberFilter('ParentItemId', $parent_item_id);
+
+ $event_params = Array (
+ 'EmailEventId' => $email_event['EventId'],
+ 'CategoryIds' => $category_ids,
+ 'ItemId' => $item_id,
+ 'ParentId' => $parent_item_id,
+ 'where_clause' => $where_clause,
+ );
+
+ $sql_event = new kEvent($event->getPrefixSpecial() . ':OnGetEventSubscribersQuery', $event_params);
+ $sql_event->MasterEvent = $event;
+ $this->HandleEvent($sql_event);
+
+ $subscribers = $this->Conn->GetIterator($sql_event->getEventParam('sql'));
+
+ if ( !count($subscribers) ) {
+ // mapping exists, but nobody has subscribed
+ return;
+ }
+
+ $send_params = Array (
+ 'Prefix' => $event->Prefix,
+ 'Special' => $event->Special,
+ 'PrefixSpecial' => $event->getPrefixSpecial(),
+ );
+
+ $send_method = $email_event['Type'] == EmailEvent::EVENT_TYPE_FRONTEND ? 'EmailEventUser' : 'EmailEventAdmin';
+
+ foreach ($subscribers as $subscriber_info) {
+ $send_params['to_name'] = $subscriber_info['SubscriberEmail'];
+ $send_params['to_email'] = $subscriber_info['SubscriberEmail'];
+ $this->Application->$send_method($email_event['Event'], $subscriber_info['UserId'], $send_params);
+ }
+ }
+
+ /**
+ * Returns filter for searching event subscribers
+ *
+ * @param string $field
+ * @param mixed $value
+ * @param bool $use_in_clause
+ * @return string
+ * @access protected
+ */
+ protected function _getSubscriberFilter($field, $value, $use_in_clause = false)
+ {
+ if ( $value ) {
+ // send to this item subscribers AND to subscribers to all items
+ $clause = $use_in_clause ? ' IN (' . $value . ')' : ' = ' . $this->Conn->qstr($value);
+
+ return $field . $clause . ' OR ' . $field . ' IS NULL';
+ }
+
+ // send to subscribers to all items
+ return $field . ' IS NULL';
+ }
+
+ /**
* Checks, that given event is implemented
*
* @param kEvent $event
Index: core/kernel/kbase.php
===================================================================
--- core/kernel/kbase.php (revision 15226)
+++ core/kernel/kbase.php (working copy)
@@ -103,6 +103,7 @@
}
}
+
class kHelper extends kBase {
/**
@@ -138,6 +139,7 @@
}
}
+
abstract class kDBBase extends kBase {
/**
@@ -1081,4 +1083,78 @@
* @access protected
*/
abstract protected function GetCol($field);
-}
\ No newline at end of file
+}
+
+
+/**
+ * Base class for exceptions, that trigger redirect action once thrown
+ */
+class kRedirectException extends Exception {
+
+ /**
+ * Redirect template
+ *
+ * @var string
+ * @access protected
+ */
+ protected $template = '';
+
+ /**
+ * Redirect params
+ *
+ * @var Array
+ * @access protected
+ */
+ protected $params = Array ();
+
+ /**
+ * Creates redirect exception
+ *
+ * @param string $message
+ * @param int $code
+ * @param Exception $previous
+ */
+ public function __construct($message = '', $code = 0, $previous = NULL)
+ {
+ parent::__construct($message, $code, $previous);
+ }
+
+ /**
+ * Initializes exception
+ *
+ * @param string $template
+ * @param Array $params
+ * @return void
+ * @access public
+ */
+ public function setup($template, $params = Array ())
+ {
+ $this->template = $template;
+ $this->params = $params;
+ }
+
+ /**
+ * Display exception details in debugger (only useful, when DBG_REDIRECT is enabled) and performs redirect
+ *
+ * @return void
+ * @access public
+ */
+ public function run()
+ {
+ $application =& kApplication::Instance();
+
+ if ( $application->isDebugMode() ) {
+ $application->Debugger->appendException($this);
+ }
+
+ $application->Redirect($this->template, $this->params);
+ }
+}
+
+
+/**
+ * Exception, that is thrown when user don't have permission to perform requested action
+ */
+class kNoPermissionException extends kRedirectException {
+
+}
Index: core/kernel/managers/request_manager.php
===================================================================
--- core/kernel/managers/request_manager.php (revision 15226)
+++ core/kernel/managers/request_manager.php (working copy)
@@ -158,6 +158,7 @@
if ( ($this->Application->RecallVar('user_id') == USER_ROOT) || $event_handler->CheckPermission($event) ) {
$this->Application->HandleEvent($event);
+ $this->Application->notifyEventSubscribers($event);
}
return $event;
Index: core/kernel/managers/rewrite_url_processor.php
===================================================================
--- core/kernel/managers/rewrite_url_processor.php (revision 15246)
+++ core/kernel/managers/rewrite_url_processor.php (working copy)
@@ -120,15 +120,17 @@
{
$url = $this->Application->GetVar('_mod_rw_url_');
- if ($url) {
+ if ( $url ) {
foreach ($this->_urlEndings as $url_ending) {
- if (substr($url, strlen($url) - strlen($url_ending)) == $url_ending) {
+ if ( substr($url, strlen($url) - strlen($url_ending)) == $url_ending ) {
$url = substr($url, 0, strlen($url) - strlen($url_ending));
$default_ending = $this->Application->ConfigValue('ModRewriteUrlEnding');
// user manually typed url with different url ending -> redirect to same url with default url ending
- if (($url_ending != $default_ending) && $this->Application->ConfigValue('ForceModRewriteUrlEnding')) {
+ if ( ($url_ending != $default_ending) && $this->Application->ConfigValue('ForceModRewriteUrlEnding') ) {
$target_url = $this->Application->BaseURL() . $url . $default_ending;
+
+ trigger_error('Mod-rewrite url "<strong>' . $_SERVER['REQUEST_URI'] . '</strong>" without "<strong>' . $default_ending . '</strong>" line ending used', E_USER_NOTICE);
$this->Application->Redirect('external:' . $target_url, Array ('response_code' => 301));
}
Index: core/kernel/utility/debugger.php
===================================================================
--- core/kernel/utility/debugger.php (revision 15226)
+++ core/kernel/utility/debugger.php (working copy)
@@ -1725,13 +1725,13 @@
}
/**
- * User-defined exception handler
+ * Adds exception details into debugger but don't cause fatal error
*
* @param Exception $exception
* @return void
* @access public
*/
- public function saveException($exception)
+ public function appendException($exception)
{
$this->ProfilerData['error_handling']['begins'] = memory_get_usage();
@@ -1751,7 +1751,18 @@
$this->ProfilerData['error_handling']['ends'] = memory_get_usage();
$this->profilerAddTotal('error_handling', 'error_handling');
+ }
+ /**
+ * User-defined exception handler
+ *
+ * @param Exception $exception
+ * @return void
+ * @access public
+ */
+ public function saveException($exception)
+ {
+ $this->appendException($exception);
$this->IsFatalError = true;
// append debugger report to data in buffer & clean buffer afterwards
Index: core/kernel/utility/http_query.php
===================================================================
--- core/kernel/utility/http_query.php (revision 15233)
+++ core/kernel/utility/http_query.php (working copy)
@@ -332,7 +332,7 @@
*
* @return void
* @access protected
- * TODO: only uses build-in rewrite listeners, when cache is build for the first time
+ * @todo: only uses build-in rewrite listeners, when cache is build for the first time
*/
protected function AfterInit()
{
@@ -361,6 +361,7 @@
$url_params['pass_category'] = 1;
$url_params['response_code'] = 301; // Moved Permanently
+ trigger_error('Non mod-rewrite url "<strong>' . $_SERVER['REQUEST_URI'] . '</strong>" used', E_USER_NOTICE);
$this->Application->Redirect('', $url_params);
}
}
Index: core/units/email_events/email_events_config.php
===================================================================
--- core/units/email_events/email_events_config.php (revision 15222)
+++ core/units/email_events/email_events_config.php (working copy)
@@ -194,6 +194,7 @@
'not_null' => 1, 'unique' => Array ('Event'), 'required' => 1, 'default' => 0
),
'LastChanged' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL),
+ 'BindToSystemEvent' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''),
),
'VirtualFields' => Array (
Index: core/units/email_events/email_events_event_handler.php
===================================================================
--- core/units/email_events/email_events_event_handler.php (revision 15225)
+++ core/units/email_events/email_events_event_handler.php (working copy)
@@ -577,6 +577,7 @@
}
$this->_validateAddress($event, 'Recipient');
+ $this->_validateBindEvent($object);
}
/**
@@ -646,6 +647,27 @@
}
/**
+ * Checks that bind event is specified in correct format and exists
+ *
+ * @param kDBItem $object
+ */
+ protected function _validateBindEvent($object)
+ {
+ $event_string = $object->GetDBField('BindToSystemEvent');
+
+ if ( !$event_string ) {
+ return;
+ }
+
+ try {
+ $this->Application->eventImplemented(new kEvent($event_string));
+ }
+ catch (Exception $e) {
+ $object->SetError('BindToSystemEvent', 'invalid_event', '+' . $e->getMessage());
+ }
+ }
+
+ /**
* Stores ids of selected phrases and redirects to export language step 1
*
* @param kEvent $event
@@ -672,4 +694,23 @@
)
);
}
+
+ /**
+ * Deletes all subscribers to e-mail event after it was deleted
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnAfterItemDelete(kEvent $event)
+ {
+ parent::OnAfterItemDelete($event);
+
+ $object = $event->getObject();
+ /* @var $object kDBItem */
+
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'EmailEventSubscribers
+ WHERE EmailEventId = ' . $object->GetID();
+ $this->Conn->Query($sql);
+ }
}
\ No newline at end of file
Index: core/units/languages/languages_item.php
===================================================================
--- core/units/languages/languages_item.php (revision 15165)
+++ core/units/languages/languages_item.php (working copy)
@@ -182,6 +182,16 @@
return false;
}
+ /**
+ * Loads item from the database by given id
+ *
+ * @access public
+ * @param mixed $id item id of keys->values hash to load item by
+ * @param string $id_field_name Optional parameter to load item by given Id field
+ * @param bool $cachable cache this query result based on it's prefix serial
+ * @return bool True if item has been loaded, false otherwise
+ * @throws kRedirectException
+ */
public function Load($id, $id_field_name = null, $cachable = true)
{
$default = false;
@@ -211,7 +221,10 @@
'pass' => 'm'
);
- $this->Application->Redirect('', $url_params);
+ $exception = new kRedirectException('Redirect into language ID = <strong>' . $language_id . '</strong> according to "<strong>Accepted-Language</strong>" header "<strong>' . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . '</strong>"');
+ $exception->setup('', $url_params);
+
+ throw $exception;
}
}
}
engine_for_subscriping_to_system_events_upgrade.patch [^] (789 bytes) 2012-03-30 12:52
[Show Content]
Index: upgrades.sql
===================================================================
--- upgrades.sql (revision 15246)
+++ upgrades.sql (working copy)
@@ -2709,3 +2709,18 @@
UPDATE CachedUrls
SET Hash = CAST((Hash & 0xFFFFFFFF) AS UNSIGNED INTEGER)
WHERE Hash < 0;
+
+ALTER TABLE EmailEvents ADD BindToSystemEvent VARCHAR(255) NOT NULL DEFAULT '';
+
+CREATE TABLE EmailEventSubscribers (
+ SubscriptionId int(11) NOT NULL AUTO_INCREMENT,
+ EmailEventId int(11) DEFAULT NULL,
+ SubscriberEmail varchar(255) NOT NULL DEFAULT '',
+ UserId int(11) DEFAULT NULL,
+ CategoryId int(11) DEFAULT NULL,
+ ItemId int(11) DEFAULT NULL,
+ ParentItemId int(11) DEFAULT NULL,
+ SubscribedOn int(11) DEFAULT NULL,
+ PRIMARY KEY (SubscriptionId),
+ KEY EmailEventId (EmailEventId)
+);
engine_for_subscriping_to_system_events_phrases.patch [^] (933 bytes) 2012-04-02 04:49
[Show Content]
Index: english.lang
===================================================================
--- english.lang (revision 15230)
+++ english.lang (working copy)
@@ -335,6 +335,7 @@
<PHRASE Label="la_fld_BackgroundPosition" Module="Core" Type="1">QmFja2dyb3VuZCBQb3NpdGlvbg==</PHRASE>
<PHRASE Label="la_fld_BackgroundRepeat" Module="Core" Type="1">QmFja2dyb3VuZCBSZXBlYXQ=</PHRASE>
<PHRASE Label="la_fld_Bcc" Module="Core" Type="1" Column="QmNj">QmNj</PHRASE>
+ <PHRASE Label="la_fld_BindToSystemEvent" Module="Core" Type="1" Hint="U3lzdGVtIEV2ZW50IGluICJwcmVmaXhbLnNwZWNpYWxdOk9uRXZlbnROYW1lIiBmb3JtYXQ=">QmluZCB0byBTeXN0ZW0gRXZlbnQ=</PHRASE>
<PHRASE Label="la_fld_BlockPosition" Module="Core" Type="1">RWxlbWVudCBQb3NpdGlvbg==</PHRASE>
<PHRASE Label="la_fld_BorderBottom" Module="Core" Type="1">Qm9yZGVyIEJvdHRvbQ==</PHRASE>
<PHRASE Label="la_fld_BorderLeft" Module="Core" Type="1">Qm9yZGVyIExlZnQ=</PHRASE>
|