/** * Method to store the item * * @access public * @return boolean True on success * @since 1.0 */ function store($data) { // Check for request forgeries if (!JFactory::getApplication()->isAdmin()) { // For flexible usage, e.g. when it is called by the new IMPORT TASK //JRequest::checkToken() or jexit( 'Invalid Token' ); } // **************************** // Initialize various variables // **************************** $db = $this->_db; $app = JFactory::getApplication(); $user = JFactory::getUser(); $dispatcher = JDispatcher::getInstance(); $cparams = $this->_cparams; $nullDate = $this->_db->getNullDate(); $view = JRequest::getVar('view', false); JRequest::setVar("isflexicontent", "yes"); $use_versioning = $cparams->get('use_versioning', 1); $print_logging_info = $cparams->get('print_logging_info'); if ($print_logging_info) { global $fc_run_times; $start_microtime = microtime(true); } // Dates displayed in the item form, are in user timezone for J2.5, and in site's default timezone for J1.5 $site_zone = $app->getCfg('offset'); $user_zone = $user->getParam('timezone', $site_zone); $tz_offset = FLEXI_J16GE ? $user_zone : $site_zone; // Sanitize id and approval flag as integers $data['vstate'] = (int) $data['vstate']; $data['id'] = (int) $data['id']; $isnew = !$data['id']; // ***************************************** // Get an item object and load existing item // ***************************************** // Get an empty item model (with default values) $item = $this->getTable('flexicontent_items', ''); // ... existing items if (!$isnew) { // Load existing item into the empty item model $item->load($data['id']); // Get item's assigned categories $query = 'SELECT DISTINCT catid FROM #__flexicontent_cats_item_relations WHERE itemid = ' . (int) $this->_id; $db->setQuery($query); $item->categories = FLEXI_J16GE ? $db->loadColumn() : $db->loadResultArray(); // We need to fake joomla's states ... when triggering the before save content event $fc_state = $item->state; if (in_array($fc_state, array(1, -5))) { $jm_state = 1; } else { if (in_array($fc_state, array(0, -3, -4))) { $jm_state = 0; } else { $jm_state = $fc_state; } } // trashed & archive states // Frontend SECURITY concern: ONLY allow to set item type for new items !!! ... or for items without type ?! if (!$app->isAdmin() && $item->type_id) { unset($data['type_id']); } } else { $item->categories = array(); } // ********************************* // Check and correct given item DATA // ********************************* // tags and cats will need some manipulation so we retieve them $tags = $this->formatToArray(@$data['tag']); $cats = $this->formatToArray(@$data['cid']); $featured_cats = $this->formatToArray(@$data['featured_cid']); unset($data['tag']); unset($data['cid']); unset($data['featured_cid']); // Make tags unique $tags = array_unique($tags); // Auto-assign a not set main category, to be the first out of secondary categories, if (empty($data['catid']) && !empty($cats[0])) { $data['catid'] = $cats[0]; } $cats_indexed = array_flip($cats); // Add the primary cat to the array if it's not already in if (@$data['catid'] && !isset($cats_indexed[$data['catid']])) { $cats[] = $data['catid']; } // Add the primary cat to the array if it's not already in if (!empty($featured_cats)) { foreach ($featured_cats as $featured_cat) { if (@$featured_cat && !isset($cats_indexed[$featured_cat])) { $cats[] = $featured_cat; } } } // ***************************** // Retrieve author configuration // ***************************** $db->setQuery('SELECT author_basicparams FROM #__flexicontent_authors_ext WHERE user_id = ' . $user->id); if ($authorparams = $db->loadResult()) { $authorparams = FLEXI_J16GE ? new JRegistry($authorparams) : new JParameter($authorparams); } // At least one category needs to be assigned if (!is_array($cats) || count($cats) < 1) { $this->setError(JText::_('FLEXI_OPERATION_FAILED') . ", " . JText::_('FLEXI_REASON') . ": " . JText::_('FLEXI_SELECT_CATEGORY')); return false; // Check more than allowed categories } else { // Get author's maximum allowed categories per item and set js limitation $max_cat_assign = !$authorparams ? 0 : intval($authorparams->get('max_cat_assign', 0)); // Verify category limitation for current author if ($max_cat_assign) { if (count($cats) > $max_cat_assign) { if (count($cats) <= count($item->categories)) { $existing_only = true; // Maximum number of categories is exceeded, but do not abort if only using existing categories foreach ($cats as $newcat) { $existing_only = $existing_only && in_array($newcat, $item->categories); } } else { $existing_only = false; } if (!$existing_only) { $this->setError(JText::_('FLEXI_OPERATION_FAILED') . ", " . JText::_('FLEXI_REASON') . ": " . JText::_('FLEXI_TOO_MANY_ITEM_CATEGORIES') . $max_cat_assign); return false; } } } } // Set back the altered categories and tags to the form data $data['categories'] = $cats; // Set it to real name of field: 'categories' INSTEAD OF 'cid' $data['tags'] = $tags; // Set it to real name of field: 'tags' INSTEAD OF 'tag' // Reconstruct (main)text field if it has splitted up e.g. to seperate editors per tab if (@$data['text'] && is_array($data['text'])) { $data['text'][0] .= preg_match('#<hr\\s+id=("|\')system-readmore("|\')\\s*\\/*>#i', $data['text'][0]) == 0 ? "\n" . '<hr id="system-readmore" />' : ""; $tabs_text = ''; foreach ($data['text'] as $tab_text) { $tabs_text .= $tab_text; } $data['text'] =& $tabs_text; } // The text field is stored in the db as to seperate fields: introtext & fulltext // So we search for the {readmore} tag and split up the text field accordingly. $pattern = '#<hr\\s+id=("|\')system-readmore("|\')\\s*\\/*>#i'; $tagPos = preg_match($pattern, @$data['text']); if ($tagPos == 0) { $data['introtext'] = @$data['text']; $data['fulltext'] = ''; } else { list($data['introtext'], $data['fulltext']) = preg_split($pattern, $data['text'], 2); $data['fulltext'] = JString::strlen(trim($data['fulltext'])) ? $data['fulltext'] : ''; } // *************************************************************************************** // Handle Parameters: attribs & metadata, merging POST values into existing values, // IF these were not set at all then there will be no need to merge, // BUT part of them may have been displayed, so we use mergeAttributes() instead of bind() // Keys that are not set will not be set, thus the previous value is maintained // *************************************************************************************** // Retrieve (a) item parameters (array PARAMS or ATTRIBS ) and (b) item metadata (array METADATA or META ) if (!FLEXI_J16GE) { $params = $this->formatToArray(@$data['params']); $metadata = $this->formatToArray(@$data['meta']); unset($data['params']); unset($data['meta']); } else { $params = $this->formatToArray(@$data['attribs']); $metadata = $this->formatToArray(@$data['metadata']); unset($data['attribs']); unset($data['metadata']); } // Merge (form posted) item attributes and metadata parameters INTO EXISTING DATA (see above for explanation) $this->mergeAttributes($item, $params, $metadata); // ******************************************************* // Retrieve submit configuration for new items in frontend // ******************************************************* if ($app->isSite() && $isnew && !empty($data['submit_conf'])) { $h = $data['submit_conf']; $session = JFactory::getSession(); $item_submit_conf = $session->get('item_submit_conf', array(), 'flexicontent'); $submit_conf = @$item_submit_conf[$h]; $autopublished = @$submit_conf['autopublished']; $overridecatperms = @$submit_conf['overridecatperms']; if ($autopublished) { // Dates forced during autopublishing if (@$submit_conf['autopublished_up_interval']) { if (FLEXI_J16GE) { $publish_up_date = JFactory::getDate(); // Gives editor's timezone by default $publish_up_date->modify('+ ' . $submit_conf['autopublished_up_interval'] . ' minutes'); $publish_up_forced = $publish_up_date->toSql(); } else { $publish_up_date = new DateTime(JHTML::_('date', JFactory::getDate()->toFormat(), '%Y-%m-%d %H:%M:%S')); $publish_up_date->modify('+ ' . $submit_conf['autopublished_up_interval'] . ' minutes'); $publish_up_forced = $publish_up_date->format('Y-m-d H:i:s'); } } if (@$submit_conf['autopublished_down_interval']) { if (FLEXI_J16GE) { $publish_down_date = JFactory::getDate(); // Gives editor's timezone by default $publish_down_date->modify('+ ' . $submit_conf['autopublished_down_interval'] . ' minutes'); $publish_down_forced = $publish_down_date->toSql(); } else { $publish_down_date = new DateTime(JHTML::_('date', JFactory::getDate()->toFormat(), '%Y-%m-%d %H:%M:%S')); $publish_down_date->modify('+ ' . $submit_conf['autopublished_down_interval'] . ' minutes'); $publish_down_forced = $publish_down_date->format('Y-m-d H:i:s'); } } } } else { $autopublished = 0; $overridecatperms = 0; } // *********************************************************** // SECURITY concern: Check form tampering of categories, of: // (a) menu overridden categories for frontent item submit // (b) or check user has 'create' privilege in item categories // *********************************************************** if ($overridecatperms) { $allowed_cid = @$submit_conf['cids']; } else { if (FLEXI_J16GE || FLEXI_ACCESS) { $allowed_cid = FlexicontentHelperPerm::getAllowedCats($user, $actions_allowed = array('core.create'), $require_all = true); } } if (isset($allowed_cid)) { // Add existing item's categories into the user allowed categories $allowed_cid = array_merge($allowed_cid, $item->categories); // Check main category tampering if (!in_array($data['catid'], $allowed_cid) && $data['catid'] != $item->catid) { $this->setError('main category is not in allowed list (form tampered ?)'); return false; } // Check multi category tampering $postcats = @$submit_conf['postcats']; if (!$isnew || !$overridecatperms || $postcats == 2) { $data['categories'] = array_intersect($data['categories'], $allowed_cid); } else { if ($postcats == 0) { $data['categories'] = $allowed_cid; } else { if ($postcats == 1) { $data['categories'] = array($data['catid']); } } } } // ***************************************************************** // SECURITY concern: Check form tampering of state related variables // ***************************************************************** // Save old main category & creator (owner) $old_created_by = $item->created_by; $old_catid = $item->catid; // New or Existing item must use the current user + new main category to calculate 'Edit State' privelege $item->created_by = $user->get('id'); $item->catid = $data['catid']; $canEditState = $this->canEditState($item, $check_cat_perm = true); // Restore old main category & creator (owner) (in case following code chooses to keep them) $item->created_by = $old_created_by; $item->catid = $old_catid; // If cannot edit state prevent user from changing state related parameters if (!$canEditState) { $data['vstate'] = 1; if (!FLEXI_J16GE) { // Behaviour is different in J1.5, it requires edit instead of edit state //unset( $data['details']['publish_up'] ); //unset( $data['details']['publish_down'] ); //unset( $data['ordering'] ); } else { unset($data['featured']); unset($data['publish_up']); unset($data['publish_down']); unset($data['ordering']); } // Check for publish up/down dates forced during auto-publishing if (@$publish_up_forced) { $data['publish_up'] = $publish_up_forced; } if (@$publish_down_forced) { $data['publish_down'] = $publish_down_forced; } $pubished_state = 1; $draft_state = -4; $pending_approval_state = -3; if (!$isnew) { // Prevent changing state of existing items by users that cannot publish $catid_changed = $old_catid != $data['catid']; if ($catid_changed && !$use_versioning) { $data['state'] = $pending_approval_state; $app->enqueueMessage('You have changed category for this content item to be a category in which you cannot publish, you content item is now in "Pending Approval" State, you will have to wait for it to be re-approved', 'warning'); } else { $data['state'] = $item->state; } } else { if ($autopublished) { // Autopublishing new item via menu configuration $data['state'] = $pubished_state; } else { // The preselected forced state of -NEW- items for users that CANNOT publish, and autopublish via menu item is disabled if ($app->isAdmin()) { $data['state'] = $cparams->get('non_publishers_item_state', $draft_state); // Use the configured setting for backend items } else { $data['state'] = $cparams->get('non_publishers_item_state_fe', $pending_approval_state); // Use the configured setting for frontend items } } } } $isSuperAdmin = FLEXI_J16GE ? $user->authorise('core.admin', 'root.1') : $user->gid >= 25; // Prevent frontend user from changing the item owner and creation date unless they are super admin if ($app->isSite() && !$isSuperAdmin) { if (!FLEXI_J16GE) { if ($isnew) { $data['details']['created_by'] = $user->get('id'); } else { unset($data['details']['created_by']); } unset($data['details']['created']); unset($data['details']['created_by_alias']); } else { if ($isnew) { $data['created_by'] = $user->get('id'); } else { unset($data['created_by']); } if (!$user->authorise('flexicontent.editcreationdate', 'com_flexicontent')) { unset($data['created']); } unset($data['created_by_alias']); } } // *********************************************************** // SECURITY concern: Check form tampering of allowed languages // *********************************************************** $allowed_langs = !$authorparams ? null : $authorparams->get('langs_allowed', null); $allowed_langs = !$allowed_langs ? null : FLEXIUtilities::paramToArray($allowed_langs); if (!$isnew && $allowed_langs) { $allowed_langs[] = $item->language; } if ($allowed_langs && isset($data['language']) && !in_array($data['language'], $allowed_langs)) { $app->enqueueMessage('You are not allowed to assign language: ' . $data['language'] . ' to Content Items', 'warning'); unset($data['language']); if ($isnew) { return false; } } if ($app->isSite() && $cparams->get('uselang_fe', 1) != 1 && isset($data['language'])) { $app->enqueueMessage('You are not allowed to set language to this content items', 'warning'); unset($data['language']); if ($isnew) { return false; } } // ************************************************ // Bind given item DATA and PARAMETERS to the model // ************************************************ // Bind the given data to the items if (!$item->bind($data)) { $this->setError($this->_db->getErrorMsg()); return false; } // Bind posted publication details (parameters) to the model for J1.5 if (!FLEXI_J16GE) { $details = $this->formatToArray(@$data['details']); $item->bind($details); } // ************************************** // Check and correct core item properties // ************************************** // -- Modification Date and Modifier, (a) new item gets null modification date and (b) existing item get the current date if ($isnew) { $item->modified = $nullDate; $item->modified_by = 0; } else { $datenow = JFactory::getDate(); $item->modified = FLEXI_J16GE ? $datenow->toSql() : $datenow->toMySQL(); $item->modified_by = $user->get('id'); } // -- Creator, if this is not already set, will be the current user or administrator if current user is not logged if (!$item->created_by) { $item->created_by = $user->get('id') ? $user->get('id') : JFactory::getUser('admin')->get('id'); } // -- Creation Date if ($item->created && JString::strlen(trim($item->created)) <= 10) { $item->created .= ' 00:00:00'; } if (FLEXI_J16GE) { $date = JFactory::getDate($item->created); $date->setTimeZone(new DateTimeZone($tz_offset)); // J2.5: Date from form field is in user's timezone } else { $date = JFactory::getDate($item->created, $tz_offset); // J1.5: Date from form field is in site's default timezone } $item->created = FLEXI_J16GE ? $date->toSql() : $date->toMySQL(); // -- Publish UP Date if ($item->publish_up && JString::strlen(trim($item->publish_up)) <= 10) { $item->publish_up .= ' 00:00:00'; } if (FLEXI_J16GE) { $date = JFactory::getDate($item->publish_up); $date->setTimeZone(new DateTimeZone($tz_offset)); // J2.5: Date from form field is in user's timezone } else { $date = JFactory::getDate($item->publish_up, $tz_offset); // J1.5: Date from form field is in site's default timezone } $item->publish_up = FLEXI_J16GE ? $date->toSql() : $date->toMySQL(); // -- Publish Down Date if (trim($item->publish_down) == JText::_('FLEXI_NEVER') || trim($item->publish_down) == '') { $item->publish_down = $nullDate; } else { if ($item->publish_down != $nullDate) { if (JString::strlen(trim($item->publish_down)) <= 10) { $item->publish_down .= ' 00:00:00'; } if (FLEXI_J16GE) { $date = JFactory::getDate($item->publish_down); $date->setTimeZone(new DateTimeZone($tz_offset)); // J2.5: Date from form field is in user's timezone } else { $date = JFactory::getDate($item->publish_down, $tz_offset); // J1.5: Date from form field is in site's default timezone } $item->publish_down = FLEXI_J16GE ? $date->toSql() : $date->toMySQL(); } } // auto assign the section if (!FLEXI_J16GE) { $item->sectionid = FLEXI_SECTION; } // For new items get next available ordering number if ($isnew) { $item->ordering = $item->getNextOrder(); } // Auto assign the default language if not set, (security of allowing language usage and of language in user's allowed languages was checked above) $item->language = $item->language ? $item->language : ($app->isSite() ? $cparams->get('default_language_fe', '*') : (FLEXI_J16GE ? '*' : flexicontent_html::getSiteDefaultLang())); // Ignore language parent id if item language is site's (content) default language, and for language 'ALL' if (substr($item->language, 0, 2) == substr(flexicontent_html::getSiteDefaultLang(), 0, 2) || $item->language == '*') { $lang_parent_id = $item->lang_parent_id; $item->lang_parent_id = $isnew ? 0 : $item->id; if ($item->lang_parent_id != $lang_parent_id && $lang_parent_id) { $app->enqueueMessage(JText::_('FLEXI_ORIGINAL_CONTENT_WAS_IGNORED'), 'message'); } } // **************************************************************************************************************** // Get version info, force version approval ON is versioning disabled, and decide new item's current version number // **************************************************************************************************************** $last_version = FLEXIUtilities::getLastVersions($item->id, true); $current_version = FLEXIUtilities::getCurrentVersions($item->id, true); // (a) Force item approval when versioning disabled $data['vstate'] = !$use_versioning ? 2 : $data['vstate']; // (b) Force item approval when item is not yet visible (is in states (a) Draft or (b) Pending Approval) $data['vstate'] = $item->state == -3 || $item->state == -4 ? 2 : $data['vstate']; // Decide new current version for the item, this depends if versioning is ON and if versioned is approved if (!$use_versioning) { // not using versioning, increment current version numbering $item->version = $isnew ? 1 : $current_version + 1; } else { // using versioning, increment last version numbering, or keep current version number if new version was not approved $item->version = $isnew ? 1 : ($data['vstate'] == 2 ? $last_version + 1 : $current_version); } // *** Item version should be zero when form was loaded with no type id, // *** thus next item form load will load default values of custom fields $item->version = $isnew && !empty($data['type_id_not_set']) ? 0 : $item->version; if ($print_logging_info) { @($fc_run_times['item_store_prepare'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } // ********************************************************************************************* // Make sure we import flexicontent AND content plugins since we will be triggering their events // ********************************************************************************************* JPluginHelper::importPlugin('flexicontent'); JPluginHelper::importPlugin('content'); // ************************************************************************************************** // Trigger Event 'onBeforeSaveItem' of FLEXIcontent plugins (such plugin is the 'flexinotify' plugin) // ************************************************************************************************** if ($print_logging_info) { $start_microtime = microtime(true); } $result = $dispatcher->trigger('onBeforeSaveItem', array(&$item, $isnew)); if (count($result) > 0 && in_array(false, $result, true)) { return false; } // cancel item save if ($print_logging_info) { $fc_run_times['onBeforeSaveItem_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10; } // ****************************************************************************************************** // Trigger Event 'OnBeforeContentSave' (J1.5) or 'onContentBeforeSave' (J2.5) of Joomla's Content plugins // ****************************************************************************************************** // Some compatibility steps if (!$isnew) { $db->setQuery('UPDATE #__content SET state = ' . $jm_state . ' WHERE id = ' . $item->id); $db->query(); } JRequest::setVar('view', 'article'); JRequest::setVar('option', 'com_content'); if ($print_logging_info) { $start_microtime = microtime(true); } if (FLEXI_J16GE) { $result = $dispatcher->trigger($this->event_before_save, array('com_content.article', &$item, $isnew)); } else { $result = $dispatcher->trigger('onBeforeContentSave', array(&$item, $isnew)); } if ($print_logging_info) { $fc_run_times['onContentBeforeSave_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10; } // Reverse compatibility steps if (!$isnew) { $db->setQuery('UPDATE #__content SET state = ' . $fc_state . ' WHERE id = ' . $item->id); $db->query(); } JRequest::setVar('view', $view); JRequest::setVar('option', 'com_flexicontent'); if (in_array(false, $result, true)) { $this->setError($item->getError()); return false; } // cancel item save // ************************************************************************************************************ // IF new item, create it before saving the fields (and constructing the search_index out of searchable fields) // ************************************************************************************************************ if ($print_logging_info) { $start_microtime = microtime(true); } if ($isnew) { $this->applyCurrentVersion($item, $data, $createonly = true); } else { // Make sure the data of the model are correct, // e.g. a getForm() used to validate input data may have set an empty item and empty id // e.g. type_id of item may have been altered by authorized users $this->_id = $item->id; $this->_item =& $item; } if ($print_logging_info) { $fc_run_times['item_store_core'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10; } // **************************************************************************** // Save fields values to appropriate tables (versioning table or normal tables) // NOTE: This allow canceling of item save operation, if 'abort' is returned // **************************************************************************** $files = JRequest::get('files', JREQUEST_ALLOWRAW); $result = $this->saveFields($isnew, $item, $data, $files); $version_approved = $isnew || $data['vstate'] == 2; if ($result === 'abort') { if ($isnew) { if (FLEXI_J16GE) { $db->setQuery('DELETE FROM #__assets WHERE id = (SELECT asset_id FROM #__content WHERE id=' . $item->id . ')'); $db->query(); } else { if (FLEXI_ACCESS) { $db->setQuery('DELETE FROM #__flexiaccess_acl WHERE acosection = `com_content` AND axosection = `item` AND axo =' . $item->id); $db->query(); } } $db->setQuery('DELETE FROM #__content WHERE id =' . $item->id); $db->query(); $db->setQuery('DELETE FROM #__flexicontent_items_ext WHERE item_id=' . $item->id); $db->query(); $this->setId(0); $this->setError($this->getError() . ' ' . JText::_('FLEXI_NEW_ITEM_NOT_CREATED')); } else { $this->setError($this->getError() . ' ' . JText::_('FLEXI_EXISTING_ITEM_NOT_SAVED')); } // Set form to reload posted data /*$session = JFactory::getSession(); $session->set('item_edit_postdata', $data, 'flexicontent');*/ return false; } // *************************************************************** // ITEM DATA SAVED: EITHER new, OR approving current item version // *************************************************************** if ($version_approved) { // ***************************** // Save item to #__content table // ***************************** if ($print_logging_info) { $start_microtime = microtime(true); } if (!$this->applyCurrentVersion($item, $data)) { return false; } if ($print_logging_info) { @($fc_run_times['item_store_core'] += round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } //echo "<pre>"; var_dump($data); exit(); // *************************** // Update Joomla Featured FLAG // *************************** if (FLEXI_J16GE) { $this->featured(array($item->id), $item->featured); } // ***************************************************************************************************** // Trigger Event 'onAfterContentSave' (J1.5) OR 'onContentAfterSave' (J2.5 ) of Joomla's Content plugins // ***************************************************************************************************** if ($print_logging_info) { $start_microtime = microtime(true); } // Some compatibility steps JRequest::setVar('view', 'article'); JRequest::setVar('option', 'com_content'); if (FLEXI_J16GE) { $dispatcher->trigger($this->event_after_save, array('com_content.article', &$item, $isnew)); } else { $dispatcher->trigger('onAfterContentSave', array(&$item, $isnew)); } // Reverse compatibility steps JRequest::setVar('view', $view); JRequest::setVar('option', 'com_flexicontent'); if ($print_logging_info) { @($fc_run_times['onContentAfterSave_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } } // ************************************************************************************************* // Trigger Event 'onAfterSaveItem' of FLEXIcontent plugins (such plugin is the 'flexinotify' plugin) // ************************************************************************************************* if ($print_logging_info) { $start_microtime = microtime(true); } $results = $dispatcher->trigger('onAfterSaveItem', array(&$item, &$data)); if ($print_logging_info) { @($fc_run_times['onAfterSaveItem_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } // ********************************************************************* // ITEM DATA NOT SAVED: NEITHER new, NOR approving current item version // ********************************************************************* if (!$version_approved) { // Warn editor that his/her changes will need approval to before becoming visible if ($canEditState) { JError::raiseNotice(11, JText::_('FLEXI_SAVED_VERSION_WAS_NOT_APPROVED_NOTICE')); } else { JError::raiseNotice(10, JText::_('FLEXI_SAVED_VERSION_MUST_BE_APPROVED_NOTICE')); } // Set modifier and modification time (as if item has been saved), so that we can use this information for updating the versioning tables $datenow = JFactory::getDate(); $item->modified = FLEXI_J16GE ? $datenow->toSql() : $datenow->toMySQL(); $item->modified_by = $user->get('id'); } // ********************************************* // Create and store version METADATA information // ********************************************* if ($print_logging_info) { $start_microtime = microtime(true); } if ($use_versioning) { $v = new stdClass(); $v->item_id = (int) $item->id; $v->version_id = $isnew && !empty($data['type_id_not_set']) ? 0 : (int) $last_version + 1; $v->created = $item->created; $v->created_by = $item->created_by; if ($item->modified != $nullDate) { // NOTE: We set modifier as creator of the version, and modication date as creation date of the version $v->created = $item->modified; $v->created_by = $item->modified_by; } $v->comment = isset($data['versioncomment']) ? htmlspecialchars($data['versioncomment'], ENT_QUOTES) : ''; $this->_db->insertObject('#__flexicontent_versions', $v); } // ************************************************************* // Delete old versions that are above the limit of kept versions // ************************************************************* $vcount = FLEXIUtilities::getVersionsCount($item->id); $vmax = $cparams->get('nr_versions', 10); if ($vcount > $vmax) { $deleted_version = FLEXIUtilities::getFirstVersion($item->id, $vmax, $current_version); $query = 'DELETE' . ' FROM #__flexicontent_items_versions' . ' WHERE item_id = ' . (int) $item->id . ' AND version <=' . $deleted_version . ' AND version!=' . (int) $current_version; $this->_db->setQuery($query); $this->_db->query(); $query = 'DELETE' . ' FROM #__flexicontent_versions' . ' WHERE item_id = ' . (int) $item->id . ' AND version_id <=' . $deleted_version . ' AND version_id!=' . (int) $current_version; $this->_db->setQuery($query); $this->_db->query(); } if ($print_logging_info) { @($fc_run_times['ver_cleanup_ver_metadata'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } // **************************************************************************************************** // Trigger Event 'onCompleteSaveItem' of FLEXIcontent plugins (such plugin is the 'flexinotify' plugin) // **************************************************************************************************** if ($print_logging_info) { $start_microtime = microtime(true); } $results = $dispatcher->trigger('onCompleteSaveItem', array(&$item, &$fields)); if ($print_logging_info) { @($fc_run_times['onCompleteSaveItem_event'] = round(1000000 * 10 * (microtime(true) - $start_microtime)) / 10); } return true; }