public function newAreaVersion($name, $action, $params = false) { $diff = ''; if ($params === false) { $params = array(); } $this->begin(); // We use the slots already queried as a basis for the new version, // because that makes rollback easy to implement etc. But we // MUST fetch the latest copy of the area object to make sure // we don't create duplicate versions. // When we're adding a new slot to an area we need to make sure it // it is first in the hash so it gets ranked first if ($action === 'add') { $diff = '<strong>' . aString::limitCharacters($params['slot']->getSearchText(), 20) . "</strong>"; $newSlots = $this->getArea($name, $params['slot'], true); } else { $newSlots = $this->getArea($name); } $area = aAreaTable::retrieveOrCreateByPageIdAndName($this->id, $name); if (!$area->id) { // We need an ID established $area->save(); } $areaVersion = new aAreaVersion(); $areaVersion->area_id = $area->id; $areaVersion->version = $area->latest_version + 1; // Don't crash on an anon edit, it's odd but you could authorize it with the 'edit' option if (sfContext::getInstance() && sfContext::getInstance()->getUser()->getGuardUser()) { $areaVersion->author_id = sfContext::getInstance()->getUser()->getGuardUser()->getId(); } if ($action === 'delete') { if (isset($newSlots[$params['permid']])) { $diff = '<strike>' . aString::limitCharacters($newSlots[$params['permid']]->getSearchText(), 20) . '</strike>'; unset($newSlots[$params['permid']]); } } elseif ($action === 'update') { $oldText = ''; if (isset($newSlots[$params['permid']])) { $oldText = $newSlots[$params['permid']]->getSearchText(); } $newText = $params['slot']->getSearchText(); $fullDiff = aString::diff($oldText, $newText); $diff = ''; if (!empty($fullDiff['onlyin1'])) { $diff .= '<strike>' . aString::limitCharacters($fullDiff['onlyin1'][0], 20) . '</strike>'; } if (!empty($fullDiff['onlyin2'])) { $diff .= '<strong>' . aString::limitCharacters($fullDiff['onlyin2'][0], 20) . '</strong>'; } $newSlots[$params['permid']] = $params['slot']; } elseif ($action === 'variant') { $newSlot = $newSlots[$params['permid']]->copy(); if (!$newSlot) { throw new sfException('Slot does not exist'); } $variants = sfConfig::get('app_a_slot_variants'); if (!isset($variants[$newSlot->type][$params['variant']])) { throw new sfException('Variant not defined for this slot type'); } $newSlot->variant = $params['variant']; // Must have an id before we can make an AreaVersionSlot referencing it $newSlot->save(); $newSlots[$params['permid']] = $newSlot; $diff = $newSlot->variant; } elseif ($action === 'add') { // We took care of this in the getArea call } elseif ($action === 'sort') { $diff = '[Reordered slots]'; $newerSlots = array(); foreach ($params['permids'] as $permid) { $newerSlots[$permid] = $newSlots[$permid]; } $newSlots = $newerSlots; } elseif ($action === 'revert') { // TODO: actually represent the changes carried out by the reversion // in the diff. That's rather expensive because many slots in the area // may have changed all at once. $diff = '[Reverted to older version]'; # We just want whatever is in the slot cache copied to a new version } $areaVersion->diff = $diff; $areaVersion->save(); $rank = 1; foreach ($newSlots as $permid => $slot) { // After unset, foreach shows keys but has null values if (!$slot) { continue; } $areaVersionSlot = new aAreaVersionSlot(); $areaVersionSlot->slot_id = $slot->id; $areaVersionSlot->permid = $permid; $areaVersionSlot->area_version_id = $areaVersion->id; $areaVersionSlot->rank = $rank++; $areaVersionSlot->save(); } $area->latest_version++; $area->save(); if (sfConfig::get('app_a_defer_search_updates', false)) { // Deferred updates are sometimes nice for performance... aLuceneUpdateTable::requestUpdate($this); } else { // ... But the average developer hates cron. // Without this the changes we just made aren't visible to getSearchText, // we need to trigger a thorough recaching aPageTable::retrieveByIdWithSlots($this->id); $this->updateLuceneIndex(); } $this->end(); }
/** * SAVE ANY CHANGES to the actual page object FIRST before you call this method. * @param mixed $name * @param mixed $action * @param mixed $params */ public function newAreaVersion($name, $action, $params = false) { // Lock this page while adding a new version to it. This prevents race conditions with the // assignment of new permids and ranks (fixes #306) aTools::lock('page_' . $this->id); $diff = ''; if ($params === false) { $params = array(); } $this->begin(); // We use the slots already queried as a basis for the new version, // because that makes rollback easy to implement etc. But we // MUST fetch the latest copy of the area object to make sure // we don't create duplicate versions. // When we're adding a new slot to an area we need to make sure it // it is first in the hash so it gets ranked first if ($action === 'add') { // New: support for specifying whether the new slot is at top or bottom of the area $top = !isset($params['top']) || $params['top']; $diff = isset($params['slot']) ? "<strong>" . aString::limitCharacters($params['slot']->getSearchText(), 20) . "</strong>" : ''; $newSlots = $this->getSlotsByAreaName($name, $params['slot'], $top); } else { $newSlots = $this->getSlotsByAreaName($name); } $area = aAreaTable::retrieveOrCreateByPageIdAndName($this->id, $name); if (!$area->id) { // We need an ID established $area->save(); } $areaVersion = new aAreaVersion(); $areaVersion->area_id = $area->id; $areaVersion->version = $area->latest_version + 1; // Don't crash on an anon edit, such as an edit made by a task if (sfContext::hasInstance() && sfContext::getInstance()->getUser()->getGuardUser()) { $areaVersion->author_id = sfContext::getInstance()->getUser()->getGuardUser()->getId(); } if ($action === 'delete') { if (isset($newSlots[$params['permid']])) { $diff = '<strike>' . aString::limitCharacters($newSlots[$params['permid']]->getSearchText(), 20) . '</strike>'; unset($newSlots[$params['permid']]); } } elseif ($action === 'update') { $oldText = ''; if (isset($newSlots[$params['permid']])) { $oldText = $newSlots[$params['permid']]->getSearchText(); } $newText = isset($params['slot']) ? $params['slot']->getSearchText() : ''; $fullDiff = aString::diff($oldText, $newText); $diff = ''; if (!empty($fullDiff['onlyin1'])) { $diff .= '<strike>' . aString::limitCharacters($fullDiff['onlyin1'][0], 20) . '</strike>'; } if (!empty($fullDiff['onlyin2'])) { $diff .= '<strong>' . aString::limitCharacters($fullDiff['onlyin2'][0], 20) . '</strong>'; } $newSlots[$params['permid']] = $params['slot']; } elseif ($action === 'variant') { $newSlot = $newSlots[$params['permid']]->copy(); if (!$newSlot) { throw new sfException('Slot does not exist'); } $variants = sfConfig::get('app_a_slot_variants'); if (!isset($variants[$newSlot->type][$params['variant']])) { throw new sfException('Variant not defined for this slot type'); } $newSlot->variant = $params['variant']; // Must have an id before we can make an AreaVersionSlot referencing it $newSlot->save(); $newSlots[$params['permid']] = $newSlot; $diff = $newSlot->variant; } elseif ($action === 'add') { // We took care of this in the getArea call } elseif ($action === 'sort') { $diff = '[Reordered slots]'; $newerSlots = array(); foreach ($params['permids'] as $permid) { $newerSlots[$permid] = $newSlots[$permid]; } $newSlots = $newerSlots; } elseif ($action === 'revert') { // TODO: actually represent the changes carried out by the reversion // in the diff. That's rather expensive because many slots in the area // may have changed all at once. $diff = '[Reverted to older version]'; # We just want whatever is in the slot cache copied to a new version } $areaVersion->diff = $diff; $areaVersion->save(); $rank = 1; foreach ($newSlots as $permid => $slot) { // After unset, foreach shows keys but has null values if (!$slot) { continue; } $areaVersionSlot = new aAreaVersionSlot(); $areaVersionSlot->slot_id = $slot->id; $areaVersionSlot->permid = $permid; $areaVersionSlot->area_version_id = $areaVersion->id; $areaVersionSlot->rank = $rank++; $areaVersionSlot->save(); } $area->latest_version++; $area->save(); $this->requestSearchUpdate(); $this->end(); aTools::unlock(); }