/**
  * DOCUMENT ME
  * @param mixed $values
  */
 public function updateObject($values = null)
 {
     if (is_null($values)) {
         $values = $this->getValues();
     }
     $oldSlug = $this->getObject()->slug;
     if (!isset($values['slug']) && isset($values['realtitle']) && $oldSlug !== '/') {
         // If they can manually edit the title but not the slug, we need to autogenerate and
         // autoupdate the slug so they have reasonable options to avoid collisions
         $oldSlug = $this->getObject()->slug;
         if (!strlen($oldSlug)) {
             // New page, provide a starter slug to replace
             $oldSlug = $this->parent->slug . '/';
         }
         $newSlug = preg_replace('|/[^/]*$|', '/' . aTools::slugify($values['realtitle'], false, false), $oldSlug);
         $suffix = '';
         $n = 0;
         while (true) {
             $values['slug'] = $newSlug . $suffix;
             if ($values['slug'] === $oldSlug) {
                 break;
             }
             $existing = Doctrine::getTable('aPage')->findOneBySlug($values['slug']);
             if (!$existing) {
                 break;
             }
             $suffix = '-' . $n;
             $n++;
         }
         $this->getObject()->slug = $values['slug'];
     }
     // Slashes break routes in most server configs. Do NOT force case of tags.
     $values['tags'] = str_replace('/', '-', isset($values['tags']) ? $values['tags'] : '');
     $object = parent::updateObject($values);
     // Check for cascading operations
     if ($this->getValue('cascade_archived')) {
         $q = Doctrine::getTable('aPage')->createQuery()->update()->where('lft > ? and rgt < ?', array($object->getLft(), $object->getRgt()));
         if ($this->getValue('cascade_archived')) {
             $q->set('archived', '?', $object->getArchived());
         }
         $q->execute();
     }
     if (isset($values['joinedtemplate'])) {
         $template = $values['joinedtemplate'];
         // $templates = aTools::getTemplates();
         list($engine, $etemplate) = preg_split('/:/', $template);
         if ($engine === 'a') {
             $object->engine = null;
         } else {
             $object->engine = $engine;
         }
         $object->template = $etemplate;
     }
     // On manual change of slug, set up a redirect from the old slug,
     // and notify child pages so they can update their slugs if they are
     // not already deliberately different
     if ($object->slug !== $oldSlug) {
         Doctrine::getTable('aRedirect')->update($oldSlug, $object);
         $children = $object->getChildren();
         foreach ($children as $child) {
             $child->updateParentSlug($oldSlug, $object->slug);
         }
     }
     if (isset($object->engine) && !strlen($object->engine)) {
         // Store it as null for plain ol' executeShow page templating
         $object->engine = null;
     }
     // A new page must be added as a child of its parent
     if ($this->parent) {
         $this->getObject()->getNode()->insertAsFirstChildOf($this->parent);
     }
     $jvalues = json_decode($this->getValue('view_groups'), true);
     // Most custom permissions are saved in separate methods called from save()
     // after the object exists. However the "Editors + Guests" group is a special
     // case which really maps to everyone who has the 'view_locked' permission, so
     // we have to scan for it in the list of groups
     foreach ($jvalues as $value) {
         if ($value['id'] === 'editors_and_guests') {
             // Editors + Guests special case
             $object->view_guest = $value['selected'] && $value['selected'] !== 'remove';
         }
     }
     // Check for cascading operations
     if ($this->getValue('cascade_archived')) {
         $q = Doctrine::getTable('aPage')->createQuery()->update()->where('lft > ? and rgt < ?', array($object->getLft(), $object->getRgt()));
         $q->set('archived', '?', $object->getArchived());
         $q->execute();
     }
     if ($values['view_options'] === 'public') {
         $object->view_admin_lock = false;
         $object->view_is_secure = false;
     } elseif ($values['view_options'] === 'login') {
         $object->view_admin_lock = false;
         $object->view_is_secure = true;
     } elseif ($values['view_options'] === 'admin') {
         $object->view_admin_lock = true;
         $object->view_is_secure = true;
     }
     if ($this->getValue('view_options_apply_to_subpages')) {
         $q = Doctrine::getTable('aPage')->createQuery()->update()->where('lft > ? and rgt < ?', array($object->getLft(), $object->getRgt()));
         $q->set('view_admin_lock', '?', $object->view_admin_lock);
         $q->set('view_is_secure', '?', $object->view_is_secure);
         $q->set('view_guest', '?', $object->view_guest);
         $q->execute();
     }
     // We have no UI for scheduling publication yet, so make sure
     // we set the publication date when we save with archived false
     if (!$values['archived']) {
         $object->setPublishedAt(aDate::mysql());
     }
     // Has to be done on shutdown so it comes after the in-memory cache of
     // sfFileCache copies itself back to disk, which otherwise overwrites
     // our attempt to invalidate the routing cache [groan]
     register_shutdown_function(array($this, 'invalidateRoutingCache'));
 }
 public function updateObject($values = null)
 {
     $oldSlug = $this->getObject()->slug;
     $object = parent::updateObject($values);
     // Check for cascading operations
     if ($this->getValue('cascade_archived') || $this->getValue('cascade_view_is_secure')) {
         $q = Doctrine::getTable('aPage')->createQuery()->update()->where('lft > ? and rgt < ?', array($object->getLft(), $object->getRgt()));
         if ($this->getValue('cascade_archived')) {
             $q->set('archived', '?', $object->getArchived());
         }
         if ($this->getValue('cascade_view_is_secure')) {
             $q->set('view_is_secure', '?', $object->getViewIsSecure());
         }
         $q->execute();
     }
     // On manual change of slug, set up a redirect from the old slug,
     // and notify child pages so they can update their slugs if they are
     // not already deliberately different
     if ($object->slug !== $oldSlug) {
         Doctrine::getTable('aRedirect')->update($oldSlug, $object);
         $children = $object->getChildren();
         foreach ($children as $child) {
             $child->updateParentSlug($oldSlug, $object->slug);
         }
     }
     if (isset($object->engine) && !strlen($object->engine)) {
         // Store it as null for plain ol' executeShow page templating
         $object->engine = null;
     }
     $this->savePrivileges($object, 'edit', 'editors');
     $this->savePrivileges($object, 'manage', 'managers');
     // Has to be done on shutdown so it comes after the in-memory cache of
     // sfFileCache copies itself back to disk, which otherwise overwrites
     // our attempt to invalidate the routing cache [groan]
     register_shutdown_function(array($this, 'invalidateRoutingCache'));
     return $object;
 }
 public function updateObject($values = null)
 {
     $object = parent::updateObject($values);
     // Check for cascading operations
     if ($this->getValue('cascade_archived') || $this->getValue('cascade_view_is_secure')) {
         $q = Doctrine::getTable('aPage')->createQuery()->update()->where('lft > ? and rgt < ?', array($object->getLft(), $object->getRgt()));
         if ($this->getValue('cascade_archived')) {
             $q->set('archived', '?', $object->getArchived());
         }
         if ($this->getValue('cascade_view_is_secure')) {
             $q->set('view_is_secure', '?', $object->getViewIsSecure());
         }
         $q->execute();
     }
     // This part isn't validation, it's just normalization.
     $slug = $object->slug;
     $slug = trim($slug);
     $slug = preg_replace("/\\/+/", "/", $slug);
     $slug = preg_match("/^(\\/.*?)\\/*\$/", $slug, $matches);
     $object->slug = $matches[1];
     if (isset($object->engine) && !strlen($object->engine)) {
         // Store it as null for plain ol' executeShow page templating
         $object->engine = null;
     }
     $this->savePrivileges($object, 'edit', 'editors');
     $this->savePrivileges($object, 'manage', 'managers');
     // Has to be done on shutdown so it comes after the in-memory cache of
     // sfFileCache copies itself back to disk, which otherwise overwrites
     // our attempt to invalidate the routing cache [groan]
     register_shutdown_function(array($this, 'invalidateRoutingCache'));
 }