public function response() { $result = new XMLElement($this->_event_name); $post_values = new XMLElement('post-values'); $fields = $_POST['fields']; if (!empty($fields)) { General::array_to_xml($post_values, $fields, true); } if (!empty($this->_error_array)) { $result->appendChild($post_values); $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); foreach ($this->_error_array as $field => $message) { $type = $fields[$field] == '' ? 'missing' : 'invalid'; $field = new XMLElement($field); $field->setAttribute('type', $type); $field->setAttribute('message', $message); $result->appendChild($field); } } else { $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('message', __('Entry created successfully.'))); } return $result; }
function action() { if ($this->_context[2] == 'saved') { $this->_context[2] = NULL; } $fields = new XMLElement('fields'); General::array_to_xml($fields, (array) $_POST['fields']); $this->_XML->appendChild($fields); parent::action(); }
/** * This function does the bulk of processing the Event, from running the delegates * to validating the data and eventually saving the data into Symphony. The result * of the Event is returned via the `$result` parameter. * * @param array $fields * An array of $_POST data, to process and add/edit an entry. * @param XMLElement $result * The XMLElement contains the result of the Event, it is passed by * reference. * @param integer $position * When the Expect Multiple filter is added, this event should expect * to deal with adding (or editing) multiple entries at once. * @param integer $entry_id * If this Event is editing an existing entry, that Entry ID will * be passed to this function. * @return XMLElement * The result of the Event */ public function __doit($fields, XMLElement &$result, $position = null, $entry_id = null) { $post_values = new XMLElement('post-values'); if (!is_array($this->eParamFILTERS)) { $this->eParamFILTERS = array(); } // Check to see if the Section of this Event is valid. if (!($section = SectionManager::fetch($this->getSource()))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Section, %s, could not be found.', array($this->getSource())))); return false; } // Create the post data element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // If the EventPreSaveFilter fails, return early if ($this->processPreSaveFilters($result, $fields, $post_values, $entry_id) === false) { return false; } // If the `$entry_id` is provided, check to see if it exists. // @todo If this was moved above PreSaveFilters, we can pass the // Entry object to the delegate meaning extensions don't have to // do that step. if (isset($entry_id)) { $entry = EntryManager::fetch($entry_id); $entry = $entry[0]; if (!is_object($entry)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Entry, %s, could not be found.', array($entry_id)))); return false; } } else { $entry = EntryManager::create(); $entry->set('section_id', $this->getSource()); } // Validate the data. `$entry->checkPostData` loops over all fields calling // checkPostFieldData function. If the return of the function is `__ENTRY_FIELD_ERROR__` // then abort the event, adding the error messages to the `$result`. if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $errors, $entry->get('id') ? true : false)) { $result = self::appendErrors($result, $fields, $errors, $post_values); return false; } else { if (__ENTRY_OK__ != $entry->setDataFromPost($fields, $errors, false, $entry->get('id') ? true : false)) { $result = self::appendErrors($result, $fields, $errors, $post_values); return false; } else { if ($entry->commit() === false) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Unknown errors where encountered when saving.'))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } else { $result->setAttributeArray(array('result' => 'success', 'type' => isset($entry_id) ? 'edited' : 'created', 'id' => $entry->get('id'))); $result->appendChild(new XMLElement('message', isset($entry_id) ? __('Entry edited successfully.') : __('Entry created successfully.'))); } } } // PASSIVE FILTERS ONLY AT THIS STAGE. ENTRY HAS ALREADY BEEN CREATED. if (in_array('send-email', $this->eParamFILTERS) && !in_array('expect-multiple', $this->eParamFILTERS)) { $result = $this->processSendMailFilter($result, $_POST['send-email'], $fields, $section, $entry); } $result = $this->processPostSaveFilters($result, $fields, $entry); $result = $this->processFinalSaveFilters($result, $fields, $entry); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return true; }
public function appendLoginStatusToEventXML(array $context = null) { $result = new XMLElement('member-login-info'); if ($this->isLoggedIn()) { $result->setAttributearray(array('logged-in' => 'yes', 'id' => $this->getMemberID(), 'result' => 'success')); } else { $result->setAttribute('logged-in', 'no'); // Append error messages if (is_array(extension_Members::$_errors) && !empty(extension_Members::$_errors)) { foreach (extension_Members::$_errors as $type => $error) { $result->appendChild(new XMLElement($type, null, array('type' => $error['type'], 'message' => $error['message'], 'label' => General::sanitize($error['label'])))); } } // Append post values to simulate a real Symphony event if (extension_Members::$_failed_login_attempt) { $result->setAttribute('result', 'error'); $post_values = new XMLElement('post-values'); $post = General::getPostData(); // Create the post data cookie element if (is_array($post['fields']) && !empty($post['fields'])) { General::array_to_xml($post_values, $post['fields'], true); $result->appendChild($post_values); } } } $context['wrapper']->appendChild($result); }
function __doit($source, $fields, &$result, &$obj, &$event, $filters, $position = NULL, $entry_id = NULL) { $post_values = new XMLElement('post-values'); $post = General::getPostData(); $filter_results = array(); ## Create the post data cookie element if (is_array($post) && !empty($post)) { General::array_to_xml($post_values, $fields, true); } ### # Delegate: EventPreSaveFilter # Description: Prior to saving entry from the front-end. This delegate will force the Event to terminate if it populates the error # array reference. Provided with references to this object, the POST data and also the error array $obj->ExtensionManager->notifyMembers('EventPreSaveFilter', '/frontend/', array('fields' => $fields, 'event' => &$event, 'messages' => &$filter_results, 'post_values' => &$post_values)); if (is_array($filter_results) && !empty($filter_results)) { foreach ($filter_results as $fr) { list($type, $status, $message) = $fr; $result->appendChild(buildFilterElement($type, $status ? 'passed' : 'failed', $message)); if (!$status) { $result->appendChild($post_values); $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); return false; } } } include_once TOOLKIT . '/class.sectionmanager.php'; include_once TOOLKIT . '/class.entrymanager.php'; $sectionManager = new SectionManager($obj); if (!($section = $sectionManager->fetch($source))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Section is invalid'))); return false; } $entryManager = new EntryManager($obj); if (isset($entry_id) && $entry_id != NULL) { $entry =& $entryManager->fetch($entry_id); $entry = $entry[0]; if (!is_object($entry)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Invalid Entry ID specified. Could not create Entry object.'))); return false; } } else { $entry =& $entryManager->create(); $entry->set('section_id', $source); } $filter_errors = array(); if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $errors, $entry->get('id') ? true : false)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); foreach ($errors as $field_id => $message) { $field = $entryManager->fieldManager->fetch($field_id); $result->appendChild(new XMLElement($field->get('element_name'), NULL, array('type' => $fields[$field->get('element_name')] == '' ? 'missing' : 'invalid', 'message' => General::sanitize($message)))); } if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } elseif (__ENTRY_OK__ != $entry->setDataFromPost($fields, $errors, false, $entry->get('id') ? true : false)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); if (isset($errors['field_id'])) { $errors = array($errors); } foreach ($errors as $err) { $field = $entryManager->fieldManager->fetch($err['field_id']); $result->appendChild(new XMLElement($field->get('element_name'), NULL, array('type' => 'invalid'))); } if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } else { if (!$entry->commit()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Unknown errors where encountered when saving.'))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } $result->setAttribute('id', $entry->get('id')); } ## PASSIVE FILTERS ONLY AT THIS STAGE. ENTRY HAS ALREADY BEEN CREATED. if (@in_array('send-email', $filters) && !@in_array('expect-multiple', $filters)) { if (!function_exists('__sendEmailFindFormValue')) { function __sendEmailFindFormValue($needle, $haystack, $discard_field_name = true, $default = NULL, $collapse = true) { if (preg_match('/^(fields\\[[^\\]]+\\],?)+$/i', $needle)) { $parts = preg_split('/\\,/i', $needle, -1, PREG_SPLIT_NO_EMPTY); $parts = array_map('trim', $parts); $stack = array(); foreach ($parts as $p) { $field = str_replace(array('fields[', ']'), '', $p); $discard_field_name ? $stack[] = $haystack[$field] : ($stack[$field] = $haystack[$field]); } if (is_array($stack) && !empty($stack)) { return $collapse ? implode(' ', $stack) : $stack; } else { $needle = NULL; } } $needle = trim($needle); if (empty($needle)) { return $default; } return $needle; } } $fields = $_POST['send-email']; $fields['recipient'] = __sendEmailFindFormValue($fields['recipient'], $_POST['fields'], true); $fields['recipient'] = preg_split('/\\,/i', $fields['recipient'], -1, PREG_SPLIT_NO_EMPTY); $fields['recipient'] = array_map('trim', $fields['recipient']); $fields['recipient'] = $obj->Database->fetch("SELECT `email`, `first_name` FROM `tbl_authors` WHERE `username` IN ('" . @implode("', '", $fields['recipient']) . "') "); $fields['subject'] = __sendEmailFindFormValue($fields['subject'], $_POST['fields'], true, __('[Symphony] A new entry was created on %s', array($obj->Configuration->get('sitename', 'general')))); $fields['body'] = __sendEmailFindFormValue($fields['body'], $_POST['fields'], false, NULL, false); $fields['sender-email'] = __sendEmailFindFormValue($fields['sender-email'], $_POST['fields'], true, 'noreply@' . parse_url(URL, PHP_URL_HOST)); $fields['sender-name'] = __sendEmailFindFormValue($fields['sender-name'], $_POST['fields'], true, 'Symphony'); $edit_link = URL . '/symphony/publish/' . $section->get('handle') . '/edit/' . $entry->get('id') . '/'; $body = __('Dear <!-- RECIPIENT NAME -->,') . General::CRLF . __('This is a courtesy email to notify you that an entry was created on the %1$s section. You can edit the entry by going to: %2$s', array($section->get('name'), $edit_link)) . General::CRLF . General::CRLF; if (is_array($fields['body'])) { foreach ($fields['body'] as $field_handle => $value) { $body .= "// {$field_handle}" . General::CRLF . $value . General::CRLF . General::CRLF; } } else { $body .= $fields['body']; } $errors = array(); if (!is_array($fields['recipient']) || empty($fields['recipient'])) { $result->appendChild(buildFilterElement('send-email', 'failed', __('No valid recipients found. Check send-email[recipient] field.'))); } else { foreach ($fields['recipient'] as $r) { list($email, $name) = array_values($r); if (!General::sendEmail($email, $fields['sender-email'], $fields['sender-name'], $fields['subject'], str_replace('<!-- RECIPIENT NAME -->', $name, $body))) { $errors[] = $email; } } if (!empty($errors)) { $xml = buildFilterElement('send-email', 'failed'); foreach ($errors as $address) { $xml->appendChild(new XMLElement('recipient', $address)); } $result->appendChild($xml); } else { $result->appendChild(buildFilterElement('send-email', 'passed')); } } } $filter_results = array(); ### # Delegate: EventPostSaveFilter # Description: After saving entry from the front-end. This delegate will not force the Events to terminate if it populates the error # array reference. Provided with references to this object, the POST data and also the error array $obj->ExtensionManager->notifyMembers('EventPostSaveFilter', '/frontend/', array('entry_id' => $entry->get('id'), 'fields' => $fields, 'entry' => $entry, 'event' => &$event, 'messages' => &$filter_results)); if (is_array($filter_results) && !empty($filter_results)) { foreach ($filter_results as $fr) { list($type, $status, $message) = $fr; $result->appendChild(buildFilterElement($type, $status ? 'passed' : 'failed', $message)); } } ### # Delegate: EventFinalSaveFilter $obj->ExtensionManager->notifyMembers('EventFinalSaveFilter', '/frontend/', array('fields' => $fields, 'event' => &$event, 'errors' => &$filter_errors, 'entry' => $entry)); $result->setAttributeArray(array('result' => 'success', 'type' => isset($entry_id) ? 'edited' : 'created')); $result->appendChild(new XMLElement('message', isset($entry_id) ? __('Entry edited successfully.') : __('Entry created successfully.'))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return true; ## End Function }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_REQUEST['fields']; $this->driver = Symphony::ExtensionManager()->create('members'); $requested_identity = $fields[extension_Members::getFieldHandle('identity')]; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Set the section ID $result = $this->setMembersSection($result, $_REQUEST['members-section-id']); if ($result->getAttribute('result') === 'error') { // We are not calling notifyMembersPasswordResetFailure here, // because this is not an authentication error $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { // We are not calling notifyMembersPasswordResetFailure here, // because this is not an authentication error return $result; } // Add any Email Templates for this event $this->addEmailTemplates('reset-password-template'); // Check that there is a row with this recovery code and that they // request a password reset $auth = $this->driver->getMemberDriver()->section->getField('authentication'); if (!$auth instanceof fieldMemberPassword) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Authentication field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Email field // has been detected $identity = $this->driver->getMemberDriver()->setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Identity field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } if (!isset($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code']) or empty($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code'])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('Recovery code is a required field.')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } $row = Symphony::Database()->fetchRow(0, sprintf("\n\t\t\t\t\tSELECT `entry_id`, `recovery-code`\n\t\t\t\t\tFROM tbl_entries_data_%d\n\t\t\t\t\tWHERE reset = 'yes'\n\t\t\t\t\tAND `recovery-code` = '%s'\n\t\t\t\t", $auth->get('id'), Symphony::Database()->cleanValue($fields[$this->driver->getMemberDriver()->section->getFieldHandle('authentication')]['recovery-code']))); if (empty($row)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member encountered errors.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'invalid', 'message-id' => EventMessages::FIELD_INVALID, 'message' => __('No recovery code found.')))); $this->notifyMembersPasswordResetFailure($requested_identity); } else { // Retrieve Member Entry record $entry = $this->driver->getMemberDriver()->fetchMemberFromID($row['entry_id']); // Check that the given Identity data matches the Member that the // recovery code is for $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (!$entry instanceof Entry || $member_id != $row['entry_id']) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, extension_Members::$_errors[$identity->get('element_name')])); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Check that the recovery code is still valid and has not expired if (is_null(Symphony::Database()->fetchVar('entry_id', 0, sprintf("\n\t\t\t\t\t\tSELECT `entry_id`\n\t\t\t\t\t\tFROM `tbl_entries_data_%d`\n\t\t\t\t\t\tWHERE `entry_id` = %d\n\t\t\t\t\t\tAND DATE_FORMAT(expires, '%%Y-%%m-%%d %%H:%%i:%%s') > '%s'\n\t\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", $auth->get('id'), $member_id, DateTimeObj::get('Y-m-d H:i:s', strtotime('now - ' . $auth->get('code_expiry'))))))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('label' => $auth->get('label'), 'type' => 'invalid', 'message-id' => MemberEventMessages::RECOVERY_CODE_INVALID, 'message' => __('Recovery code has expired.')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // Create new password using the auth field so simulate the checkPostFieldData // and processRawFieldData functions. $message = ''; // For the purposes of this event, the auth field should ALWAYS be required // as we have to set a password (ie. handle the case where this field is // actually optional) RE: #193 $auth->set('required', 'yes'); $status = $auth->checkPostFieldData($fields[$auth->get('element_name')], $message, $member_id); if (Field::__OK__ != $status) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($auth->get('element_name'), null, array('type' => $status == Field::__MISSING_FIELDS__ ? 'missing' : 'invalid', 'message' => $message, 'message-id' => $status == Field::__MISSING_FIELDS__ ? EventMessages::FIELD_MISSING : EventMessages::FIELD_INVALID, 'label' => $auth->get('label')))); $this->notifyMembersPasswordResetFailure($requested_identity); $result->appendChild($post_values); return $result; } // processRawFieldData will encode the user's new password with the current one $status = Field::__OK__; $data = $auth->processRawFieldData(array('password' => Symphony::Database()->cleanValue($fields[$auth->get('element_name')]['password'])), $status); $data['recovery-code'] = null; $data['reset'] = 'no'; $data['expires'] = null; // Update the database with the new password, removing the recovery code and setting // reset to no. Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); /** * Fired just after a Member has reset their password. * * @delegate MembersPostResetPassword * @param string $context * '/frontend/' * @param integer $member_id * The Member ID of the member who just reset their password */ Symphony::ExtensionManager()->notifyMembers('MembersPostResetPassword', '/frontend/', array('member_id' => $member_id)); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); if (extension_Members::getSetting('reset-password-auto-login') == "yes") { // Instead of replicating the same logic, call the UpdatePasswordLogin which will // handle relogging in the user. $this->driver->getMemberDriver()->filter_UpdatePasswordLogin(array('entry' => $entry, 'fields' => array($this->driver->getMemberDriver()->section->getFieldHandle('authentication') => array('password' => Symphony::Database()->cleanValue($fields[$auth->get('element_name')]['password']))))); } if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); } $result->appendChild($post_values); return $result; }
private function getXML($position = 0, $entry_id = NULL) { // Cache stuff that can be reused between filter fields and entries static $post; static $postValues; // Remember if $post contains multiple entries or not static $expectMultiple; $xml = new XMLElement('data'); // Get post values if (empty($postValues) || $position > 0) { // TODO: handle post of multiple entries at the same time if (empty($post)) { $post = General::getPostData(); // Check if post contains multiple entries or not // TODO: make some hidden field required for post, so we can check for sure // if $post['fields'][0]['conditionalizer'] exists? $expectMultiple = is_array($post['fields']) && is_array($post['fields'][0]) ? true : false; } if (!empty($post['fields']) && is_array($post['fields'])) { $postValues = new XMLElement('post'); if ($expectMultiple == true) { if (!empty($entry_id) && isset($post['id'])) { // $entry_id overrides $position foreach ($post['id'] as $pos => $id) { if ($id == $entry_id) { $position = $pos; break; } } } else { if (isset($post['id'][$position]) && is_numeric($post['id'][$position])) { $entry_id = $post['id'][$position]; } } $postValues->setAttribute('position', $position); General::array_to_xml($postValues, $post['fields'][$position], false); } else { if ($position < 1) { if (empty($entry_id) && isset($post['id']) && is_numeric($post['id'])) { $entry_id = $post['id']; } General::array_to_xml($postValues, $post['fields'], false); } else { // TODO: add error element? } } } } if (!empty($postValues)) { $xml->appendChild($postValues); } // Get old entry $entry = NULL; if (!class_exists('EntryManager')) { include_once TOOLKIT . '/class.entrymanager.php'; } if (!empty($entry_id)) { $entry = EntryManager::fetch($entry_id); $entry = $entry[0]; if (is_object($entry)) { $entry_xml = new XMLElement('old-entry'); $entry_xml->setAttribute('position', $position); $this->appendEntryXML($entry_xml, $entry); $xml->appendChild($entry_xml); } else { $entry = NULL; } } else { $entry = EntryManager::create(); $entry->set('section_id', $this->get('parent_section')); } // Set new entry data. Code found in event.section.php: // https://github.com/symphonycms/symphony-2/blob/29244318e4de294df780513ee027edda767dd75a/symphony/lib/toolkit/events/event.section.php#L99 if (is_object($entry)) { self::$recursion = true; if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($expectMultiple ? $post['fields'][$position] : $post['fields'], $errors, $entry->get('id') ? true : false)) { // Return early - other fields will mark their errors self::$recursion = false; return self::__OK__; } else { if (__ENTRY_OK__ != $entry->setDataFromPost($expectMultiple ? $post['fields'][$position] : $post['fields'], $errors, true, $entry->get('id') ? true : false)) { // Return early - other fields will mark their errors. self::$recursion = false; return self::__OK__; } } self::$recursion = false; $entry_xml = new XMLElement('entry'); $entry_xml->setAttribute('position', $position); $this->appendEntryXML($entry_xml, $entry); $xml->appendChild($entry_xml); } // Get author if ($temp = Symphony::Engine()->Author) { $author = new XMLElement('author'); $author->setAttribute('id', $temp->get('id')); $author->setAttribute('user_type', $temp->get('user_type')); $author->setAttribute('primary', $temp->get('primary')); $author->setAttribute('username', $temp->get('username')); $author->setAttribute('first_name', $temp->get('first_name')); $author->setAttribute('last_name', $temp->get('last_name')); $xml->appendChild($author); } return $xml; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; $this->driver = Symphony::ExtensionManager()->create('members'); // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Set the section ID $result = $this->setMembersSection($result, $_REQUEST['members-section-id']); if ($result->getAttribute('result') === 'error') { $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('regenerate-activation-code-template'); $activation = $this->driver->getMemberDriver()->section->getField('activation'); if (!$activation instanceof fieldMemberActivation) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Activation field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Password field // has been detected $identity = $this->driver->getMemberDriver()->setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Identity field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild($post_values); return $result; } if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('label' => $identity->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('%s is a required field.', array($identity->get('label')))))); $result->appendChild($post_values); return $result; } // Make sure we dont accidently use an expired code $activation->purgeCodes(); // Check that a member exists first before proceeding. $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, extension_Members::$_errors[$identity->get('element_name')])); $result->appendChild($post_values); return $result; } // Check that the current member isn't already activated. If they // are, no point in regenerating the code. $entry = $this->driver->getMemberDriver()->fetchMemberFromID($member_id); if ($entry->getData($activation->get('id'), true)->activated == 'yes') { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('label' => $activation->get('label'), 'type' => 'invalid', 'message-id' => MemberEventMessages::ACTIVATION_PRE_COMPLETED, 'message' => __('Member is already activated.')))); $result->appendChild($post_values); return $result; } // Regenerate the code $status = Field::__OK__; $data = $activation->processRawFieldData(array('activated' => 'no'), $status); // If the Member has entry data for the Activation field, update it to yes if (array_key_exists((int) $activation->get('id'), $entry->getData())) { Symphony::Database()->update($data, 'tbl_entries_data_' . $activation->get('id'), ' `entry_id` = ' . $member_id); } else { $data['entry_id'] = $member_id; Symphony::Database()->insert($data, 'tbl_entries_data_' . $activation->get('id')); } /** * Fired just after a Member has regenerated their activation code * for their account. * * @delegate MembersPostRegenerateActivationCode * @param string $context * '/frontend/' * @param integer $member_id * The Member ID of the member who just requested a new activation code * @param string $activation_code * The new activation code for this Member */ Symphony::ExtensionManager()->notifyMembers('MembersPostRegenerateActivationCode', '/frontend/', array('member_id' => $member_id, 'activation_code' => $data['code'])); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('activation-code', $data['code'])); $result->appendChild($post_values); return $result; }
protected function __trigger() { $api = new MailChimp($this->_driver->getKey()); $result = new XMLElement("mailchimp"); $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); $list = isset($_POST['list']) ? $_POST['list'] : $this->_driver->getList(); // For post values $fields = $_POST; unset($fields['action']); // Valid email? if (!$email) { $error = new XMLElement('error', 'E-mail is invalid.'); $error->setAttribute("handle", 'email'); $result->appendChild($error); $result->setAttribute("result", "error"); return $result; } // Default subscribe parameters $params = array('email' => array('email' => $email), 'id' => $list, 'merge_vars' => array(), 'email_type' => $fields['email_type'] ? $fields['email_type'] : 'html', 'double_optin' => $fields['double_optin'] ? $fields['double_optin'] == 'yes' : true, 'update_existing' => $fields['update_existing'] ? $fields['update_existing'] == 'yes' : false, 'replace_interests' => $fields['replace_interests'] ? $fields['replace_interests'] == 'yes' : true, 'send_welcome' => $fields['send_welcome'] ? $fields['send_welcome'] == 'yes' : false); // Are we merging? try { $mergeVars = $api->call('lists/merge-vars', array('id' => array($list))); $mergeVars = $mergeVars['success_count'] ? $mergeVars['data'][0]['merge_vars'] : array(); if (count($mergeVars) > 1 && isset($fields['merge'])) { $merge = $fields['merge']; foreach ($merge as $key => $val) { if (!empty($val)) { $params['merge_vars'][$key] = $val; } else { unset($fields['merge'][$key]); } } } // Subscribe the user $api_result = $api->call('lists/subscribe', $params); if ($api_result['status'] == 'error') { $result->setAttribute("result", "error"); // try to match mergeVars with error if (count($mergeVars) > 1) { // replace foreach ($mergeVars as $var) { $errorMessage = str_replace($var['tag'], $var['name'], $api_result['error'], $count); if ($count == 1) { $error = new XMLElement("message", $errorMessage); break; } } } // no error message found with merge vars in it if ($error == null) { $msg = General::sanitize($api_result['error']); $error = new XMLElement("message", strlen($msg) > 0 ? $msg : 'Unknown error', array('code' => $api_result['code'], 'name' => $api_result['name'])); } $result->appendChild($error); } else { if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } else { $result->setAttribute("result", "success"); $result->appendChild(new XMLElement('message', __('Subscriber added to list successfully'))); } } // Set the post values $post_values = new XMLElement("post-values"); General::array_to_xml($post_values, $fields); $result->appendChild($post_values); } catch (Exception $ex) { $error = new XMLElement('error', General::wrapInCDATA($ex->getMessage())); $result->appendChild($error); } return $result; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; $driver = Symphony::ExtensionManager()->create('members'); // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // If a member is logged in, return early with an error if ($driver->getMemberDriver()->isLoggedIn()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('You cannot generate a recovery code while being logged in.')))); $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('generate-recovery-code-template'); // Check that either a Member: Username or Member: Password field // has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } // Check that a member exists first before proceeding. if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($identity->get('label'))), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Generate new password $newPassword = General::generatePassword(); // Set the Entry password to be reset and the current timestamp $auth = extension_Members::getField('authentication'); $status = Field::__OK__; $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); $entry_data = $entry->getData(); // Generate a Recovery Code with the same logic as a normal password $data = $auth->processRawFieldData(array('password' => General::hash($newPassword . $member_id, 'sha1')), $status); $data['recovery-code'] = $data['password']; $data['reset'] = 'yes'; $data['expires'] = DateTimeObj::get('Y-m-d H:i:s', time()); // Overwrite the password with the old password data. This prevents // a users account from being locked out if it it just reset by a random // member of the public $data['password'] = $entry_data[$auth->get('id')]['password']; $data['length'] = $entry_data[$auth->get('id')]['length']; $data['strength'] = $entry_data[$auth->get('id')]['strength']; Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('recovery-code', $data['recovery-code'])); $result->appendChild($post_values); return $result; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; $this->driver = Symphony::ExtensionManager()->create('members'); // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Set the section ID $result = $this->setMembersSection($result, $_REQUEST['members-section-id']); if ($result->getAttribute('result') === 'error') { $result->appendChild($post_values); return $result; } // If a member is logged in, return early with an error if ($this->driver->getMemberDriver()->isLoggedIn()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('You cannot generate a recovery code while being logged in.'), array('message-id' => MemberEventMessages::ALREADY_LOGGED_IN))); $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('generate-recovery-code-template'); // Check that either a Member: Username or Member: Password field // has been detected $identity = $this->driver->getMemberDriver()->setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('No Identity field found.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild($post_values); return $result; } // Check that a member exists first before proceeding. if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('label' => $identity->get('label'), 'type' => 'missing', 'message-id' => EventMessages::FIELD_MISSING, 'message' => __('%s is a required field.', array($identity->get('label')))))); $result->appendChild($post_values); return $result; } $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Member event encountered errors when processing.'), array('message-id' => MemberEventMessages::MEMBER_ERRORS))); $result->appendChild(new XMLElement($identity->get('element_name'), null, extension_Members::$_errors[$identity->get('element_name')])); $result->appendChild($post_values); return $result; } // Find the Authentication fiedl $auth = $this->driver->getMemberDriver()->section->getField('authentication'); $status = Field::__OK__; // Generate new password $newPassword = $auth->generatePassword(); $entry = $this->driver->getMemberDriver()->fetchMemberFromID($member_id); $entry_data = $entry->getData(); // Generate a Recovery Code with the same logic as a normal password $data = $auth->processRawFieldData(array('password' => $auth->encodePassword($newPassword . $member_id)), $status); // Set the Entry password to be reset and the current timestamp $data['recovery-code'] = SHA1::hash($newPassword . $member_id); $data['reset'] = 'yes'; $data['expires'] = DateTimeObj::get('Y-m-d H:i:s', time()); // If the Member has entry data for the Authentication field, update it if (array_key_exists((int) $auth->get('id'), $entry_data)) { // Overwrite the password with the old password data. This prevents // a users account from being locked out if it it just reset by a random // member of the public $data['password'] = $entry_data[$auth->get('id')]['password']; $data['length'] = $entry_data[$auth->get('id')]['length']; $data['strength'] = $entry_data[$auth->get('id')]['strength']; Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); } else { $data['entry_id'] = $member_id; Symphony::Database()->insert($data, 'tbl_entries_data_' . $auth->get('id')); } /** * Fired just after a Member has requested a recovery code so they * can reset their password. * * @delegate MembersPostForgotPassword * @param string $context * '/frontend/' * @param integer $member_id * The Member ID of the member who just requested a recovery * code. * @param string $recovery_code * The recovery code that was generated for this Member */ Symphony::ExtensionManager()->notifyMembers('MembersPostForgotPassword', '/frontend/', array('member_id' => $member_id, 'recovery_code' => $data['recovery-code'])); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('recovery-code', $data['recovery-code'])); $result->appendChild($post_values); return $result; }
public function appendEventXML(array $context = null) { $result = new XMLElement('paypal'); $cookie = new Cookie('paypal', TWO_WEEKS, __SYM_COOKIE_PATH__, null, true); $accessToken = $cookie->get('token'); //$accessToken->getRefreshToken() // var_dump($accessToken);die; if (!empty($accessToken)) { $user = $cookie->get('user'); $result->appendChild(General::array_to_xml($result, $user)); } else { $baseUrl = SYMPHONY_URL . '/extension/paypal/consent'; // ### Get User Consent URL // The clientId is stored in the bootstrap file //Get Authorization URL returns the redirect URL that could be used to get user's consent $redirectUrl = OpenIdSession::getAuthorizationUrl($baseUrl, array('openid', 'profile', 'address', 'email', 'phone', 'https://uri.paypal.com/services/paypalattributes', 'https://uri.paypal.com/services/expresscheckout'), null, null, null, $this->apiContext); $authend = $this->mode == 'sandbox' ? '"authend": "sandbox",' : ''; $scriptInclude = '<span id="lippButton"></span> <script src="https://www.paypalobjects.com/js/external/api.js"></script> <script> paypal.use( ["login"], function(login) { login.render ({ "appid": "' . $this->clientId . '",' . $authend . '"scopes": "openid profile email address phone https://uri.paypal.com/services/paypalattributes https://uri.paypal.com/services/expresscheckout", "containerid": "lippButton", "locale": "en-us", "returnurl": "' . $baseUrl . '" }); }); </script>'; $result->appendChild(new XMLElement('authorize', $this->repairEntities($scriptInclude), array('url' => $this->repairEntities($redirectUrl)))); // var_dump($redirectUrl);die; } $context['wrapper']->appendChild($result); }
public function eventPreSaveFilter($context) { if ($context['fields'] === null && (RestEngine::getHTTPMethod() === 'put' || 'post')) { $parsedData = RestEngine::parseBodyContent(); if ($context['entry_id'] === null && RestEngine::getHTTPMethod() === 'put') { $pageID = RestEngine::getPageID(); $urlParams = $this::getPageURLParams(); //use the page ID to look up the format and uid param settings $settings = RestResourceManager::getByPageID($pageID); if (array_key_exists($settings['uid_parameter'], $urlParams)) { $entryIDValue = $urlParams[$settings['uid_parameter']]; if ($settings['field_id'] == 0) { // 0 stands for using the Entry ID number directly so just // check to see if that entry number exists in the correct section $entrySection = EntryManager::fetchEntrySectionID($entryIDValue); if ($entrySection == $settings['section_id']) { //good to go $entryID = $entryIDValue; } } else { $fieldType = FieldManager::fetchFieldTypeFromID($settings['field_id']); //TODO: Eventually add in a more robust field type management to distinguish between value and handle based fields if necessary, or do it by array searching? if ($fieldType != 'memberemail') { $query = "SELECT `entry_id` FROM `tbl_entries_data_" . $settings['field_id'] . "` WHERE `handle` = '" . $entryIDValue . "' LIMIT 1"; } else { $query = "SELECT `entry_id` FROM `tbl_entries_data_" . $settings['field_id'] . "` WHERE `value` = '" . $entryIDValue . "' LIMIT 1"; } $entryID = Symphony::Database()->fetchVar('entry_id', 0, $query); } if (is_null($entryID)) { //no matching entry $context['messages'][] = array('restengine:invalid-id', FALSE, __('The specified resource "%1$s" does not exist.', array($entryIDValue))); } else { //good to go $context['entry_id'] = $entryID; } } else { $context['messages'][] = array('restengine:settings-error', FALSE, __('Invalid Rest Resource unique ID URL parameter: %1$s.', array($settings['uid_parameter']))); //probably some kind of error needs returning here } } if (is_array($parsedData) && !empty($parsedData['data']) && $parsedData['errors'] === null) { //Create the post data cookie element. General::array_to_xml($context['post_values'], $parsedData, true); //TODO: check for field mapping //TODO: Do we need to error when message body contains properties that we don't have fields for in the assigned section? $context['fields'] = $parsedData['data']; } } }
/** * Dumps sections to XMLElement. * * @param $sections * * @return XMLElement */ private function buildOutput($sections) { $result = new XMLElement('sections'); foreach ($sections as $handle => $section) { foreach ($section['entries'] as $entry) { $post_values = new XMLElement('post-values'); General::array_to_xml($post_values, $entry['orig_fields'], true); $rep_post_values = new XMLElement('rep-post-values'); General::array_to_xml($rep_post_values, $entry['fields'], true); $entry['result']->appendChild($post_values); $entry['result']->appendChild($rep_post_values); $entry['result']->appendChild($entry['res_entry']); $entry['result']->appendChild($entry['res_fields']); $entry['result']->appendChild($entry['res_filters']); $section['result']->appendChild($entry['result']); } $result->appendChild($section['result']); } return $result; }
/** * Append element to datasource output */ public function appendFormattedElement(&$wrapper, $data, $encode = false) { $node = new XMLElement($this->get('element_name')); $newsletter = EmailNewsletterManager::create($data['newsletter_id']); $properties = $newsletter->getStats(); $node->setAttribute('newsletter-id', $data['newsletter_id']); $node->setAttribute('started-on', $properties['started_on']); $node->setAttribute('started-by', $properties['started_by']); $node->setAttribute('completed-on', $properties['completed_on']); $node->setAttribute('status', $properties['status']); $node->setAttribute('total', $properties['total']); $node->setAttribute('sent', $properties['sent']); $node->setAttribute('failed', $properties['failed']); $node->appendChild(new XMLElement('subject', $newsletter->getTemplate()->subject)); // load configuration; // use saved (entry) config XML if available (i.e.: if the email newsletter has been sent); // fallback: the field's configuration XML // sender $sender = new XMLElement('sender'); $about = is_object($newsletter->getSender()) ? $newsletter->getSender()->about() : array(); General::array_to_xml($sender, $about); $sender_name = $about['name']; $sender_handle = is_object($newsletter->getSender()) ? $newsletter->getSender()->getHandle() : NULL; $el = new XMLElement('name'); $el->setAttribute('id', $sender_handle); $el->setValue($sender_name); $sender->replaceChildAt(0, $el); $node->appendChild($sender); // recipients $recipients = new XMLElement('recipient-groups'); foreach ($newsletter->getRecipientGroups() as $group) { $rgroup = new XMLElement('group'); $about = (array) $group->about(); General::array_to_xml($rgroup, $about); $rgroup_name = $about['name']; $rgroup_handle = $group->getHandle(); $el = new XMLElement('name'); $el->setAttribute('id', $rgroup_handle); $el->setValue($rgroup_name); $rgroup->replaceChildAt(0, $el); $rgroup_count = RecipientgroupManager::create($rgroup_handle)->getCount(); $rgroup->setAttribute('count', $rgroup_count); $recipients->appendChild($rgroup); } $node->appendChild($recipients); // template $template = new XMLElement('template'); $about = (array) $newsletter->getTemplate()->about; General::array_to_xml($template, $about); $template_name = $about['name']; $template_handle = EmailTemplateManager::getHandleFromName($template_name); $el = new XMLElement('name'); $el->setAttribute('id', $template_handle); $el->setValue($template_name); $template->replaceChildAt(0, $el); $node->appendChild($template); $wrapper->appendChild($node); }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('activate-account-template'); // Do sanity checks on the incoming data $activation = extension_Members::getField('activation'); if (!$activation instanceof fieldMemberActivation) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Activation field found.')))); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Email field has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } // Ensure that the Member: Activation field has been provided if (!isset($fields[$activation->get('element_name')]) or empty($fields[$activation->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($activation->get('label'))), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } else { $fields[$activation->get('element_name')] = trim($fields[$activation->get('element_name')]); } // Check that a member exists first before proceeding. $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Retrieve Member's entry $driver = Symphony::ExtensionManager()->create('members'); $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); if ($entry->getData($activation->get('id'), true)->activated == 'yes') { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member is already activated.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Make sure we dont accidently use an expired code $activation->purgeCodes(); $code = $activation->isCodeActive($member_id); if ($code['code'] != $fields[$activation->get('element_name')]) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Activation error. Code was invalid or has expired.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Got to here, then everything is awesome. $status = Field::__OK__; $data = $activation->processRawFieldData(array('activated' => 'yes', 'timestamp' => DateTimeObj::get('Y-m-d H:i:s', time()), 'code' => null), $status); // Update the database setting activation to yes. Symphony::Database()->update($data, 'tbl_entries_data_' . $activation->get('id'), ' `entry_id` = ' . $member_id); // Update our `$entry` object with the new activation data $entry->setData($activation->get('id'), $data); // Simulate an array to login with. $data_fields = array_merge($fields, array(extension_Members::getFieldHandle('authentication') => $entry->getData(extension_Members::getField('authentication')->get('id'), true)->password)); // Only login if the Activation field allows auto login. if (extension_Members::getSetting('activate-account-auto-login') == 'no' || $driver->getMemberDriver()->login($data_fields, true)) { // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); } else { if (extension_Members::getSetting('activate-account-auto-login') == 'yes') { if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'error'); } } $result->appendChild($post_values); return $result; }
public function __viewPreview() { $this->setPageType('index'); $this->setTitle(__("Symphony - Newsletter Recipient Groups Preview")); $sectionManager = new SectionManager($this); try { $source = RecipientgroupManager::create($this->_context[1]); } catch (Exception $e) { Administration::instance()->errorPageNotFound(); } if ($_GET['pg']) { $source->dsParamSTARTPAGE = (int) $_GET['pg']; } $source->dsParamLIMIT = 17; $elements = $source->getSlice(); $recipients = new XMLElement('recipients'); General::array_to_xml($recipients, $source->about()); General::array_to_xml($recipients, array('source' => is_numeric($section = $source->getSource()) ? $sectionManager->fetch($source->getSource())->get('handle') : 'system:' . $source->getSource())); General::array_to_xml($recipients, $elements); $context = new XMLElement('context'); General::array_to_xml($context, $this->_context); $this->_XML->appendChild($context); $this->_XML->appendChild($recipients); $this->insertBreadcrumbs(array(Widget::Anchor(__('Email Newsletter Recipients'), SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/'))); $about = $source->about(); $this->appendSubheading($about['name'] . ' ' . __('preview'), array(Widget::Anchor(__('Edit %s group', array($layout)), SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/edit/' . $source->getHandle() . '/' . $layout, __('Edit %s group', array($layout)), 'button'))); }
/** * This function does the bulk of processing the Event, from running the delegates * to validating the data and eventually saving the data into Symphony. The result * of the Event is returned via the `$result` parameter. * * @param array $fields * An array of $_POST data, to process and add/edit an entry. * @param XMLElement $result * The XMLElement contains the result of the Event, it is passed by * reference. * @param integer $position * When the Expect Multiple filter is added, this event should expect * to deal with adding (or editing) multiple entries at once. * @param integer $entry_id * If this Event is editing an existing entry, that Entry ID will * be passed to this function. * @throws Exception * @return XMLElement * The result of the Event */ public function __doit(array $fields = array(), XMLElement &$result, $position = null, $entry_id = null) { $post_values = new XMLElement('post-values'); if (!is_array($this->eParamFILTERS)) { $this->eParamFILTERS = array(); } // Check to see if the Section of this Event is valid. if (!($section = SectionManager::fetch($this->getSource()))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Section, %s, could not be found.', array($this->getSource())), array('message-id' => EventMessages::SECTION_MISSING))); return false; } // Create the post data element if (!empty($fields)) { General::array_to_xml($post_values, $fields, true); } // If the EventPreSaveFilter fails, return early if ($this->processPreSaveFilters($result, $fields, $post_values, $entry_id) === false) { return false; } // If the `$entry_id` is provided, check to see if it exists. // @todo If this was moved above PreSaveFilters, we can pass the // Entry object to the delegate meaning extensions don't have to // do that step. if (isset($entry_id)) { $entry = EntryManager::fetch($entry_id); $entry = $entry[0]; if (!is_object($entry)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Entry, %s, could not be found.', array($entry_id)), array('message-id' => EventMessages::ENTRY_MISSING))); return false; } // `$entry_id` wasn't provided, create a new Entry object. } else { $entry = EntryManager::create(); $entry->set('section_id', $this->getSource()); } // Validate the data. `$entry->checkPostData` loops over all fields calling // their `checkPostFieldData` function. If the return of the function is // `Entry::__ENTRY_FIELD_ERROR__` then abort the event and add the error // messages to the `$result`. if (Entry::__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $errors, $entry->get('id') ? true : false)) { $result = self::appendErrors($result, $fields, $errors, $post_values); return false; // If the data is good, process the data, almost ready to save it to the // Database. If processing fails, abort the event and display the errors } elseif (Entry::__ENTRY_OK__ != $entry->setDataFromPost($fields, $errors, false, $entry->get('id') ? true : false)) { $result = self::appendErrors($result, $fields, $errors, $post_values); return false; // Data is checked, data has been processed, by trying to save the // Entry caused an error to occur, so abort and return. } elseif ($entry->commit() === false) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Unknown errors where encountered when saving.'), array('message-id' => EventMessages::ENTRY_UNKNOWN))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; // Entry was created, add the good news to the return `$result` } else { $result->setAttributeArray(array('result' => 'success', 'type' => isset($entry_id) ? 'edited' : 'created', 'id' => $entry->get('id'))); if (isset($entry_id)) { $result->appendChild(new XMLElement('message', __('Entry edited successfully.'), array('message-id' => EventMessages::ENTRY_EDITED_SUCCESS))); } else { $result->appendChild(new XMLElement('message', __('Entry created successfully.'), array('message-id' => EventMessages::ENTRY_CREATED_SUCCESS))); } } // PASSIVE FILTERS ONLY AT THIS STAGE. ENTRY HAS ALREADY BEEN CREATED. if (in_array('send-email', $this->eParamFILTERS) && !in_array('expect-multiple', $this->eParamFILTERS)) { $result = $this->processSendMailFilter($result, $_POST['send-email'], $fields, $section, $entry); } $result = $this->processPostSaveFilters($result, $fields, $entry); $result = $this->processFinalSaveFilters($result, $fields, $entry); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return true; }
public function __doit($fields, &$result, $position = null, $entry_id = null) { $post_values = new XMLElement('post-values'); $filter_results = array(); if (!is_array($this->eParamFILTERS)) { $this->eParamFILTERS = array(); } // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } /** * Prior to saving entry from the front-end. This delegate will * force the Event to terminate if it populates the `$filter_results` * array. All parameters are passed by reference. * * @delegate EventPreSaveFilter * @param string $context * '/frontend/' * @param array $fields * @param Event $this * @param array $messages * An associative array of array's which contain 4 values, * the name of the filter (string), the status (boolean), * the message (string) an optionally an associative array * of additional attributes to add to the filter element. * @param XMLElement $post_values * @param integer $entry_id * If editing an entry, this parameter will be an integer, * otherwise null. */ Symphony::ExtensionManager()->notifyMembers('EventPreSaveFilter', '/frontend/', array('fields' => &$fields, 'event' => &$this, 'messages' => &$filter_results, 'post_values' => &$post_values, 'entry_id' => &$entry_id)); if (is_array($filter_results) && !empty($filter_results)) { $can_proceed = true; foreach ($filter_results as $fr) { list($name, $status, $message, $attributes) = $fr; $result->appendChild($this->buildFilterElement($name, $status ? 'passed' : 'failed', $message, $attributes)); if ($status === false) { $can_proceed = false; } } if ($can_proceed !== true) { $result->appendChild($post_values); $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); return false; } } include_once TOOLKIT . '/class.sectionmanager.php'; include_once TOOLKIT . '/class.entrymanager.php'; if (!($section = SectionManager::fetch($this->getSource()))) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Section, %s, could not be found.', array($this->getSource())))); return false; } if (isset($entry_id)) { $entry =& EntryManager::fetch($entry_id); $entry = $entry[0]; if (!is_object($entry)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('The Entry, %s, could not be found.', array($entry_id)))); return false; } } else { $entry =& EntryManager::create(); $entry->set('section_id', $this->getSource()); } if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $errors, $entry->get('id') ? true : false)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); foreach ($errors as $field_id => $message) { $field = FieldManager::fetch($field_id); if (is_array($fields[$field->get('element_name')])) { $type = array_reduce($fields[$field->get('element_name')], array('SectionEvent', '__reduceType')); } else { $type = $fields[$field->get('element_name')] == '' ? 'missing' : 'invalid'; } $result->appendChild(new XMLElement($field->get('element_name'), null, array('label' => General::sanitize($field->get('label')), 'type' => $type, 'message' => General::sanitize($message)))); } if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } elseif (__ENTRY_OK__ != $entry->setDataFromPost($fields, $errors, false, $entry->get('id') ? true : false)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); foreach ($errors as $field_id => $message) { $field = FieldManager::fetch($field_id); $result->appendChild(new XMLElement($field->get('element_name'), null, array('label' => General::sanitize($field->get('label')), 'type' => 'invalid', 'message' => General::sanitize($message)))); } if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } else { if (!$entry->commit()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('message', __('Unknown errors where encountered when saving.'))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return false; } $result->setAttribute('id', $entry->get('id')); } // PASSIVE FILTERS ONLY AT THIS STAGE. ENTRY HAS ALREADY BEEN CREATED. if (in_array('send-email', $this->eParamFILTERS) && !in_array('expect-multiple', $this->eParamFILTERS)) { if (!function_exists('__sendEmailFindFormValue')) { function __sendEmailFindFormValue($needle, $haystack, $discard_field_name = true, $default = null, $collapse = true) { if (preg_match('/^(fields\\[[^\\]]+\\],?)+$/i', $needle)) { $parts = preg_split('/\\,/i', $needle, -1, PREG_SPLIT_NO_EMPTY); $parts = array_map('trim', $parts); $stack = array(); foreach ($parts as $p) { $field = str_replace(array('fields[', ']'), '', $p); $discard_field_name ? $stack[] = $haystack[$field] : ($stack[$field] = $haystack[$field]); } if (is_array($stack) && !empty($stack)) { return $collapse ? implode(' ', $stack) : $stack; } else { $needle = null; } } $needle = trim($needle); if (empty($needle)) { return $default; } return $needle; } } $fields = $_POST['send-email']; $db = Symphony::Database(); $fields['recipient'] = __sendEmailFindFormValue($fields['recipient'], $_POST['fields'], true); $fields['recipient'] = preg_split('/\\,/i', $fields['recipient'], -1, PREG_SPLIT_NO_EMPTY); $fields['recipient'] = array_map('trim', $fields['recipient']); $fields['subject'] = __sendEmailFindFormValue($fields['subject'], $_POST['fields'], true, __('[Symphony] A new entry was created on %s', array(Symphony::Configuration()->get('sitename', 'general')))); $fields['body'] = __sendEmailFindFormValue($fields['body'], $_POST['fields'], false, null, false); $fields['sender-email'] = __sendEmailFindFormValue($fields['sender-email'], $_POST['fields'], true, null); $fields['sender-name'] = __sendEmailFindFormValue($fields['sender-name'], $_POST['fields'], true, null); $fields['reply-to-name'] = __sendEmailFindFormValue($fields['reply-to-name'], $_POST['fields'], true, null); $fields['reply-to-email'] = __sendEmailFindFormValue($fields['reply-to-email'], $_POST['fields'], true, null); $edit_link = SYMPHONY_URL . '/publish/' . $section->get('handle') . '/edit/' . $entry->get('id') . '/'; $language = Symphony::Configuration()->get('lang', 'symphony'); $template_path = Event::getNotificationTemplate($language); $body = sprintf(file_get_contents($template_path), $section->get('name'), $edit_link); if (is_array($fields['body'])) { foreach ($fields['body'] as $field_handle => $value) { $body .= "// {$field_handle}" . PHP_EOL . $value . PHP_EOL . PHP_EOL; } } else { $body .= $fields['body']; } // Loop over all the recipients and attempt to send them an email // Errors will be appended to the Event XML $errors = array(); foreach ($fields['recipient'] as $recipient) { $author = AuthorManager::fetchByUsername($recipient); if (empty($author)) { $errors['recipient'][$recipient] = __('Recipient not found'); continue; } $email = Email::create(); // Huib: Exceptions are also thrown in the settings functions, not only in the send function. // Those Exceptions should be caught too. try { $email->recipients = array($author->get('first_name') => $author->get('email')); if ($fields['sender-name'] != null) { $email->sender_name = $fields['sender-name']; } if ($fields['sender-email'] != null) { $email->sender_email_address = $fields['sender-email']; } if ($fields['reply-to-name'] != null) { $email->reply_to_name = $fields['reply-to-name']; } if ($fields['reply-to-email'] != null) { $email->reply_to_email_address = $fields['reply-to-email']; } $email->text_plain = str_replace('<!-- RECIPIENT NAME -->', $author->get('first_name'), $body); $email->subject = $fields['subject']; $email->send(); } catch (EmailValidationException $e) { $errors['address'][$author->get('email')] = $e->getMessage(); } catch (EmailGatewayException $e) { // The current error array does not permit custom tags. // Therefore, it is impossible to set a "proper" error message. // Will return the failed email address instead. $errors['gateway'][$author->get('email')] = $e->getMessage(); } catch (EmailException $e) { // Because we don't want symphony to break because it can not send emails, // all exceptions are logged silently. // Any custom event can change this behaviour. $errors['email'][$author->get('email')] = $e->getMessage(); } } // If there were errors, output them to the event if (!empty($errors)) { $xml = $this->buildFilterElement('send-email', 'failed'); foreach ($errors as $type => $messages) { $xType = new XMLElement('error'); $xType->setAttribute('error-type', $type); foreach ($messages as $recipient => $message) { $xType->appendChild(new XMLElement('message', $message, array('recipient' => $recipient))); } $xml->appendChild($xType); } $result->appendChild($xml); } else { $result->appendChild($this->buildFilterElement('send-email', 'passed')); } } $filter_results = array(); /** * After saving entry from the front-end. This delegate will not force * the Events to terminate if it populates the `$filter_results` array. * Provided with references to this object, the `$_POST` data and also * the error array * * @delegate EventPostSaveFilter * @param string $context * '/frontend/' * @param integer $entry_id * @param array $fields * @param Entry $entry * @param Event $this * @param array $messages * An associative array of array's which contain 4 values, * the name of the filter (string), the status (boolean), * the message (string) an optionally an associative array * of additional attributes to add to the filter element. */ Symphony::ExtensionManager()->notifyMembers('EventPostSaveFilter', '/frontend/', array('entry_id' => $entry->get('id'), 'fields' => $fields, 'entry' => $entry, 'event' => &$this, 'messages' => &$filter_results)); if (is_array($filter_results) && !empty($filter_results)) { foreach ($filter_results as $fr) { list($name, $status, $message, $attributes) = $fr; $result->appendChild($this->buildFilterElement($name, $status ? 'passed' : 'failed', $message, $attributes)); } } $filter_errors = array(); /** * This delegate that lets extensions know the final status of the * current Event. It is triggered when everything has processed correctly. * The `$messages` array contains the results of the previous filters that * have executed, and the `$errors` array contains any errors that have * occurred as a result of this delegate. These errors cannot stop the * processing of the Event, as that has already been done. * * * @delegate EventFinalSaveFilter * @param string $context * '/frontend/' * @param array $fields * @param Event $this * @param array $messages * An associative array of array's which contain 4 values, * the name of the filter (string), the status (boolean), * the message (string) an optionally an associative array * of additional attributes to add to the filter element. * @param array $errors * An associative array of array's which contain 4 values, * the name of the filter (string), the status (boolean), * the message (string) an optionally an associative array * of additional attributes to add to the filter element. * @param Entry $entry */ Symphony::ExtensionManager()->notifyMembers('EventFinalSaveFilter', '/frontend/', array('fields' => $fields, 'event' => $this, 'messages' => $filter_results, 'errors' => &$filter_errors, 'entry' => $entry)); if (is_array($filter_errors) && !empty($filter_errors)) { foreach ($filter_errors as $fr) { list($name, $status, $message, $attributes) = $fr; $result->appendChild($this->buildFilterElement($name, $status ? 'passed' : 'failed', $message, $attributes)); } } $result->setAttributeArray(array('result' => 'success', 'type' => isset($entry_id) ? 'edited' : 'created')); $result->appendChild(new XMLElement('message', isset($entry_id) ? __('Entry edited successfully.') : __('Entry created successfully.'))); if (isset($post_values) && is_object($post_values)) { $result->appendChild($post_values); } return true; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('regenerate-activation-code-template'); $activation = extension_Members::getField('activation'); if (!$activation instanceof fieldMemberActivation) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Activation field found.')))); $result->appendChild($post_values); return $result; } // Check that either a Member: Username or Member: Password field // has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($identity->get('label'))), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Make sure we dont accidently use an expired code $activation->purgeCodes(); // Check that a member exists first before proceeding. $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Check that the current member isn't already activated. If they // are, no point in regenerating the code. $driver = Symphony::ExtensionManager()->create('members'); $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); if ($entry->getData($activation->get('id'), true)->activated == 'yes') { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($activation->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member is already activated.'), 'label' => $activation->get('label')))); $result->appendChild($post_values); return $result; } // Regenerate the code $status = Field::__OK__; $data = $activation->processRawFieldData(array('activated' => 'no'), $status); // Update the database setting activation to yes. Symphony::Database()->update($data, 'tbl_entries_data_' . $activation->get('id'), ' `entry_id` = ' . $member_id); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('activation-code', $data['code'])); $result->appendChild($post_values); return $result; }