public static function savePermissionsFor($role_id, $permissions)
 {
     if (!Record::existsIn('Role', 'id = :role_id', array(':role_id' => $role_id))) {
         return false;
     }
     if (!self::deleteWhere('RolePermission', 'role_id = :role_id', array(':role_id' => (int) $role_id))) {
         return false;
     }
     foreach ($permissions as $perm) {
         $rp = new RolePermission(array('role_id' => $role_id, 'permission_id' => $perm->id));
         if (!$rp->save()) {
             return false;
         }
     }
     return true;
 }
 /**
  * Runs checks and stores a page.
  *
  * @param string $action   What kind of action this is: add or edit.
  * @param mixed $id        Page to edit if any.
  */
 private function _store($action, $id = false)
 {
     // Sanity checks
     if ($action == 'edit' && !$id) {
         throw new Exception('Trying to edit page when $id is false.');
     }
     use_helper('Validate');
     $data = $_POST['page'];
     $data['is_protected'] = !empty($data['is_protected']) ? 1 : 0;
     Flash::set('post_data', (object) $data);
     // Add pre-save checks here
     $errors = false;
     // CSRF checks
     if (isset($_POST['csrf_token'])) {
         $csrf_token = $_POST['csrf_token'];
         $csrf_id = '';
         if ($action === 'edit') {
             $csrf_id = '/' . $id;
         }
         if (!SecureToken::validateToken($csrf_token, BASE_URL . 'page/' . $action . $csrf_id)) {
             $errors[] = __('Invalid CSRF token found!');
         }
     } else {
         $errors[] = __('No CSRF token found!');
     }
     $data['title'] = trim($data['title']);
     if (empty($data['title'])) {
         $errors[] = __('You have to specify a title!');
     }
     // Make sure we have a slug
     if (isset($data['slug'])) {
         $data['slug'] = trim($data['slug']);
     } else {
         $data['slug'] = '';
     }
     if (empty($data['slug']) && $id != '1') {
         $errors[] = __('You have to specify a slug!');
     } else {
         if ($data['slug'] == ADMIN_DIR) {
             $errors[] = __('You cannot have a slug named :slug!', array(':slug' => ADMIN_DIR));
         }
         // Make sure home's slug is passed ok, but other slugs are validated properly
         if ($id != '1' && (!Validate::slug($data['slug']) || empty($data['slug'])) || $id == '1' && !empty($data['slug'])) {
             $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => 'slug'));
         }
         if (Record::existsIn('Page', 'parent_id = :parent_id AND slug = :slug AND id <> :id', array(':parent_id' => $data['parent_id'], ':slug' => $data['slug'], ':id' => $id))) {
             $errors[] = __('Page with slug <b>:slug</b> already exists!', array(':slug' => $data['slug']));
         }
     }
     // Check all numerical fields for a page
     $fields = array('parent_id', 'layout_id', 'needs_login');
     foreach ($fields as $field) {
         if (!Validate::digit($data[$field])) {
             $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => $field));
         }
     }
     // Check all date fields for a page
     $fields = array('created_on', 'published_on', 'valid_until');
     foreach ($fields as $field) {
         if (isset($data[$field])) {
             $data[$field] = trim($data[$field]);
             if (!empty($data[$field]) && !(bool) preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/D', (string) $data[$field])) {
                 $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => $field));
             }
         }
     }
     // Check all time fields for a page
     $fields = array('created_on_time', 'published_on_time', 'valid_until_time');
     foreach ($fields as $field) {
         if (isset($data[$field])) {
             $data[$field] = trim($data[$field]);
             if (!empty($data[$field]) && !(bool) preg_match('/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/D', (string) $data[$field])) {
                 $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => $field));
             }
         }
     }
     // Check alphanumerical fields
     $fields = array('keywords', 'description');
     foreach ($fields as $field) {
         use_helper('Kses');
         $data[$field] = kses(trim($data[$field]), array());
         /*
                     if (!empty($data[$field]) && !Validate::alpha_comma($data[$field])) {
            $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => $field));
                     }
         * 
         */
     }
     // Check behaviour_id field
     if (!empty($data['behaviour_id']) && !Validate::slug($data['behaviour_id'])) {
         $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => 'behaviour_id'));
     }
     // Check is_protected field
     if (!empty($data['is_protected']) && !AuthUser::hasPermission('admin_edit')) {
         $errors[] = __('Only administrators can change <b>protected</b> status of pages!');
         unset($data['is_protected']);
     }
     // Make sure the title doesn't contain HTML
     if (Setting::get('allow_html_title') == 'off') {
         use_helper('Kses');
         $data['title'] = kses(trim($data['title']), array());
     }
     // Create the page object to be manipulated and populate data
     if ($action == 'add') {
         $page = new Page($data);
     } else {
         $page = Record::findByIdFrom('Page', $id);
         $page->setFromData($data);
     }
     // Upon errors, rebuild original page and return to screen with errors
     if (false !== $errors) {
         $tags = $_POST['page_tag'];
         // Rebuild time fields
         if (isset($page->created_on)) {
             $page->created_on = $page->created_on . ' ' . $page->created_on_time;
         }
         if (isset($page->published_on)) {
             $page->published_on = $page->published_on . ' ' . $page->published_on_time;
         }
         if (isset($page->valid_until)) {
             $page->valid_until = $page->valid_until . ' ' . $page->valid_until_time;
         }
         // Rebuild parts
         $part = $_POST['part'];
         if (!empty($part)) {
             $tmp = false;
             foreach ($part as $key => $val) {
                 $tmp[$key] = (object) $val;
             }
             $part = $tmp;
         }
         // Set the errors to be displayed.
         Flash::setNow('error', implode('<br/>', $errors));
         // display things ...
         $this->setLayout('backend');
         $this->display('page/edit', array('action' => $action, 'csrf_token' => SecureToken::generateToken(BASE_URL . 'page/' . $action . $csrf_id), 'page' => (object) $page, 'tags' => $tags, 'filters' => Filter::findAll(), 'behaviors' => Behavior::findAll(), 'page_parts' => (object) $part, 'layouts' => Record::findAllFrom('Layout')));
     }
     // Notify
     if ($action == 'add') {
         Observer::notify('page_add_before_save', $page);
     } else {
         Observer::notify('page_edit_before_save', $page);
     }
     // Time to actually save the page
     // @todo rebuild this so parts are already set before save?
     // @todo determine lazy init impact
     if ($page->save()) {
         // Get data for parts of this page
         $data_parts = $_POST['part'];
         Flash::set('post_parts_data', (object) $data_parts);
         if ($action == 'edit') {
             $old_parts = PagePart::findByPageId($id);
             // check if all old page part are passed in POST
             // if not ... we need to delete it!
             foreach ($old_parts as $old_part) {
                 $not_in = true;
                 foreach ($data_parts as $part_id => $data) {
                     $data['name'] = trim($data['name']);
                     if ($old_part->name == $data['name']) {
                         $not_in = false;
                         // this will not really create a new page part because
                         // the id of the part is passed in $data
                         $part = new PagePart($data);
                         $part->page_id = $id;
                         Observer::notify('part_edit_before_save', $part);
                         $part->save();
                         Observer::notify('part_edit_after_save', $part);
                         unset($data_parts[$part_id]);
                         break;
                     }
                 }
                 if ($not_in) {
                     $old_part->delete();
                 }
             }
         }
         // add the new parts
         foreach ($data_parts as $data) {
             $data['name'] = trim($data['name']);
             $part = new PagePart($data);
             $part->page_id = $page->id;
             Observer::notify('part_add_before_save', $part);
             $part->save();
             Observer::notify('part_add_after_save', $part);
         }
         // save tags
         $page->saveTags($_POST['page_tag']['tags']);
         Flash::set('success', __('Page has been saved!'));
     } else {
         Flash::set('error', __('Page has not been saved!'));
         $url = 'page/';
         $url .= $action == 'edit' ? 'edit/' . $id : 'add/';
         redirect(get_url($url));
     }
     if ($action == 'add') {
         Observer::notify('page_add_after_save', $page);
     } else {
         Observer::notify('page_edit_after_save', $page);
     }
     // save and quit or save and continue editing ?
     if (isset($_POST['commit'])) {
         redirect(get_url('page'));
     } else {
         redirect(get_url('page/edit/' . $page->id));
     }
 }
 /**
  * @todo merge _add() and _edit() into one _store()
  *
  * @param <type> $id
  */
 private function _edit($id)
 {
     use_helper('Validate');
     $data = $_POST['user'];
     Flash::set('post_data', (object) $data);
     // Add pre-save checks here
     $errors = false;
     // CSRF checks
     if (isset($_POST['csrf_token'])) {
         $csrf_token = $_POST['csrf_token'];
         if (!SecureToken::validateToken($csrf_token, BASE_URL . 'user/edit/' . $id)) {
             Flash::set('error', __('Invalid CSRF token found!'));
             redirect(get_url('user/edit/' . $id));
         }
     } else {
         Flash::set('error', __('No CSRF token found!'));
         redirect(get_url('user/edit/' . $id));
     }
     // check if user want to change the password
     if (strlen($data['password']) > 0) {
         // check if pass and confirm are egal and >= 5 chars
         if (strlen($data['password']) >= 5 && $data['password'] == $data['confirm']) {
             unset($data['confirm']);
         } else {
             Flash::set('error', __('Password and Confirm are not the same or too small!'));
             redirect(get_url('user/edit/' . $id));
         }
     } else {
         unset($data['password'], $data['confirm']);
     }
     // Check alphanumerical fields
     $fields = array('username');
     foreach ($fields as $field) {
         if (!empty($data[$field]) && !Validate::alphanum_space($data[$field])) {
             $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => $field));
         }
     }
     if (!empty($data['name']) && !Validate::alphanum_space($data['name'], true)) {
         $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => 'name'));
     }
     if (!empty($data['email']) && !Validate::email($data['email'])) {
         $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => 'email'));
     }
     if (!empty($data['language']) && !Validate::alpha_dash($data['language'])) {
         $errors[] = __('Illegal value for :fieldname field!', array(':fieldname' => 'language'));
     }
     // Check if user with the same 'username' already exists
     if (Record::existsIn('User', 'username=:username', array(':username' => $data['username']))) {
         $errors[] = __('Username <b>:username</b> is already in use, please choose other!', array(':username' => $data['username']));
     }
     if ($errors !== false) {
         // Set the errors to be displayed.
         Flash::set('error', implode('<br/>', $errors));
         redirect(get_url('user/edit/' . $id));
     }
     $user = Record::findByIdFrom('User', $id);
     if (isset($data['password'])) {
         if (empty($user->salt)) {
             $user->salt = AuthUser::generateSalt();
         }
         $data['password'] = AuthUser::generateHashedPassword($data['password'], $user->salt);
     }
     $user->setFromData($data);
     if ($user->save()) {
         if (AuthUser::hasPermission('user_edit')) {
             // now we need to add roles
             $data = isset($_POST['user_role']) ? $_POST['user_role'] : array();
             UserRole::setRolesFor($user->id, $data);
         }
         Flash::set('success', __('User has been saved!'));
         Observer::notify('user_after_edit', $user->name, $user->id);
     } else {
         Flash::set('error', __('User has not been saved!'));
     }
     if (AuthUser::getId() == $id) {
         redirect(get_url('user/edit/' . $id));
     } else {
         redirect(get_url('user'));
     }
 }