public function save($FormPostValues, $Settings = false)
{
// Define the primary key in this model's table.
$this->defineSchema();
// Get data from form
$CategoryID = val('CategoryID', $FormPostValues);
$NewName = val('Name', $FormPostValues, '');
$UrlCode = val('UrlCode', $FormPostValues, '');
$AllowDiscussions = val('AllowDiscussions', $FormPostValues, '');
$CustomPermissions = (bool) val('CustomPermissions', $FormPostValues) || is_array(val('Permissions', $FormPostValues));
$CustomPoints = val('CustomPoints', $FormPostValues, null);
if (isset($FormPostValues['AllowedDiscussionTypes']) && is_array($FormPostValues['AllowedDiscussionTypes'])) {
$FormPostValues['AllowedDiscussionTypes'] = dbencode($FormPostValues['AllowedDiscussionTypes']);
}
// Is this a new category?
$Insert = $CategoryID > 0 ? false : true;
if ($Insert) {
$this->addInsertFields($FormPostValues);
}
$this->addUpdateFields($FormPostValues);
// Add some extra validation to the url code if one is provided.
if ($Insert || array_key_exists('UrlCode', $FormPostValues)) {
$this->Validation->applyRule('UrlCode', 'Required');
$this->Validation->applyRule('UrlCode', 'UrlStringRelaxed');
// Url slugs cannot be the name of a CategoriesController method or fully numeric.
$this->Validation->addRule('CategorySlug', 'regex:/^(?!(all|archives|discussions|index|table|[0-9]+)$).*/');
$this->Validation->applyRule('UrlCode', 'CategorySlug', 'Url code cannot be numeric or the name of an internal method.');
// Make sure that the UrlCode is unique among categories.
$this->SQL->select('CategoryID')->from('Category')->where('UrlCode', $UrlCode);
if ($CategoryID) {
$this->SQL->where('CategoryID <>', $CategoryID);
}
if ($this->SQL->get()->numRows()) {
$this->Validation->addValidationResult('UrlCode', 'The specified url code is already in use by another category.');
}
}
if (isset($FormPostValues['ParentCategoryID'])) {
if (empty($FormPostValues['ParentCategoryID'])) {
$FormPostValues['ParentCategoryID'] = -1;
} else {
$parent = CategoryModel::categories($FormPostValues['ParentCategoryID']);
if (!$parent) {
$FormPostValues['ParentCategoryID'] = -1;
}
}
}
// Prep and fire event.
$this->EventArguments['FormPostValues'] =& $FormPostValues;
$this->EventArguments['CategoryID'] = $CategoryID;
$this->fireEvent('BeforeSaveCategory');
// Validate the form posted values.
if ($this->validate($FormPostValues, $Insert)) {
$Fields = $this->Validation->schemaValidationFields();
$Fields = $this->coerceData($Fields);
unset($Fields['CategoryID']);
$Fields['AllowDiscussions'] = (bool) val('AllowDiscussions', $Fields);
if ($Insert === false) {
$OldCategory = $this->getID($CategoryID, DATASET_TYPE_ARRAY);
if (null === val('AllowDiscussions', $FormPostValues, null)) {
$AllowDiscussions = $OldCategory['AllowDiscussions'];
// Force the allowdiscussions property
}
$Fields['AllowDiscussions'] = (bool) $AllowDiscussions;
// Figure out custom points.
if ($CustomPoints !== null) {
if ($CustomPoints) {
$Fields['PointsCategoryID'] = $CategoryID;
} else {
$Parent = self::categories(val('ParentCategoryID', $Fields, $OldCategory['ParentCategoryID']));
$Fields['PointsCategoryID'] = val('PointsCategoryID', $Parent, 0);
}
}
$this->update($Fields, array('CategoryID' => $CategoryID));
// Check for a change in the parent category.
if (isset($Fields['ParentCategoryID']) && $OldCategory['ParentCategoryID'] != $Fields['ParentCategoryID']) {
$this->rebuildTree();
} else {
self::setCache($CategoryID, $Fields);
}
} else {
$CategoryID = $this->insert($Fields);
if ($CategoryID) {
if ($CustomPermissions) {
$this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID));
}
if ($CustomPoints) {
$this->SQL->put('Category', array('PointsCategoryID' => $CategoryID), array('CategoryID' => $CategoryID));
}
}
$this->rebuildTree();
// Safeguard to make sure that treeleft and treeright cols are added
}
// Save the permissions
if ($CategoryID) {
// Check to see if this category uses custom permissions.
if ($CustomPermissions) {
$permissionModel = Gdn::permissionModel();
if (is_array(val('Permissions', $FormPostValues))) {
// The permissions were posted in an API format provided by settings/getcategory
$permissions = val('Permissions', $FormPostValues);
foreach ($permissions as &$perm) {
$perm['JunctionTable'] = 'Category';
$perm['JunctionColumn'] = 'PermissionCategoryID';
$perm['JunctionID'] = $CategoryID;
}
} else {
// The permissions were posted in the web format provided by settings/addcategory and settings/editcategory
$permissions = $permissionModel->pivotPermissions(val('Permission', $FormPostValues, array()), array('JunctionID' => $CategoryID));
}
$permissionModel->saveAll($permissions, array('JunctionID' => $CategoryID, 'JunctionTable' => 'Category'));
if (!$Insert) {
// Figure out my last permission and tree info.
$Data = $this->SQL->select('PermissionCategoryID, TreeLeft, TreeRight')->from('Category')->where('CategoryID', $CategoryID)->get()->firstRow(DATASET_TYPE_ARRAY);
// Update this category's permission.
$this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('CategoryID' => $CategoryID));
// Update all of my children that shared my last category permission.
$this->SQL->put('Category', array('PermissionCategoryID' => $CategoryID), array('TreeLeft >' => $Data['TreeLeft'], 'TreeRight <' => $Data['TreeRight'], 'PermissionCategoryID' => $Data['PermissionCategoryID']));
self::clearCache();
}
} elseif (!$Insert) {
// Figure out my parent's permission.
$NewPermissionID = $this->SQL->select('p.PermissionCategoryID')->from('Category c')->join('Category p', 'c.ParentCategoryID = p.CategoryID')->where('c.CategoryID', $CategoryID)->get()->value('PermissionCategoryID', 0);
if ($NewPermissionID != $CategoryID) {
// Update all of my children that shared my last permission.
$this->SQL->put('Category', array('PermissionCategoryID' => $NewPermissionID), array('PermissionCategoryID' => $CategoryID));
self::clearCache();
}
// Delete my custom permissions.
$this->SQL->delete('Permission', array('JunctionTable' => 'Category', 'JunctionColumn' => 'PermissionCategoryID', 'JunctionID' => $CategoryID));
}
}
// Force the user permissions to refresh.
Gdn::userModel()->clearPermissions();
// $this->RebuildTree();
} else {
$CategoryID = false;
}
return $CategoryID;
}