diff --git a/content/content.index.php b/content/content.index.php
index 71b033f..ba20055 100644
--- a/content/content.index.php
+++ b/content/content.index.php
@@ -21,7 +21,7 @@ function __construct(){
*/
public function build($context)
{
- if(Administration::instance()->Author->isDeveloper()) {
+ if(Symphony::Author()->isDeveloper()) {
if($_POST['with-selected'] == 'delete' && is_array($_POST['items']))
{
foreach($_POST['items'] as $id_role => $value)
diff --git a/content/content.roles.php b/content/content.roles.php
index 08eae0b..03b9050 100644
--- a/content/content.roles.php
+++ b/content/content.roles.php
@@ -170,9 +170,16 @@ public function viewForm()
$divEntries = new XMLElement('div', null, array('class'=>'sub entries'));
$label = Widget::Label();
// check if this checkbox is checked:
- $attributes = $this->checkSection($id, 'own_entries') == 1 ? array('checked'=>'checked') : null;
- $input = Widget::Input('section['.$id.'][own_entries]', null, 'checkbox', $attributes);
- $label->setValue($input->generate() . ' ' . __('Author can view/edit own entries only'));
+ $attributes = $this->checkSection($id, 'view_own_entries') == 1 ? array('checked'=>'checked') : null;
+ $input = Widget::Input('section['.$id.'][view_own_entries]', null, 'checkbox', $attributes);
+ $label->setValue($input->generate() . ' ' . __('Author can view own entries only'));
+ $divEntries->appendChild($label);
+
+ $label = Widget::Label();
+ // check if this checkbox is checked:
+ $attributes = $this->checkSection($id, 'edit_own_entries') == 1 ? array('checked'=>'checked') : null;
+ $input = Widget::Input('section['.$id.'][edit_own_entries]', null, 'checkbox', $attributes);
+ $label->setValue($input->generate() . ' ' . __('Author can edit own entries only'));
$divEntries->appendChild($label);
$label = Widget::Label();
diff --git a/extension.driver.php b/extension.driver.php
index b521cba..ec2a1b4 100644
--- a/extension.driver.php
+++ b/extension.driver.php
@@ -1,19 +1,6 @@
'Author Roles',
- 'version' => '1.2',
- 'release-date' => '2012-10-04',
- 'author' => array(
- 'name' => 'Twisted Interactive',
- 'website' => 'http://www.twisted.nl'),
- 'description' => 'Author Roles for Symphony 2.2 and above'
- );
- }
// Set the delegates:
public function getSubscribedDelegates()
@@ -49,19 +36,427 @@ public function getSubscribedDelegates()
'delegate' => 'AdminPagePreGenerate',
'callback' => 'checkCallback'
),
- array(
- 'page' => '/backend/',
- 'delegate' => 'InitaliseAdminPageHead',
- 'callback' => 'makePreAdjustements'
- ),
array(
'page' => '/system/authors/',
'delegate' => 'AddDefaultAuthorAreas',
'callback' => 'modifyAreas'
- )
+ ),
+ array(
+ 'page' => '/publish/',
+ 'delegate' => 'AdjustPublishFiltering',
+ 'callback' => 'adjustPublishFiltering'
+ ),
+ array(
+ 'page' => '/publish/edit/',
+ 'delegate' => 'EntryPreRender',
+ 'callback' => 'entryPreRender'
+ ),
+ array(
+ 'page' => '/publish/edit/',
+ 'delegate' => 'EntryPreEdit',
+ 'callback' => 'entryPreEdit'
+ ),
+ array(
+ 'page' => '/publish/new/',
+ 'delegate' => 'EntryPreCreate',
+ 'callback' => 'entryPreCreate'
+ ),
+ array(
+ 'page' => '/publish/',
+ 'delegate' => 'EntryPreDelete',
+ 'callback' => 'entryPreDelete'
+ ),
+ array(
+ 'page' => '/system/preferences/',
+ 'delegate' => 'AddCustomPreferenceFieldsets',
+ 'callback' => 'appendPreferences'
+ ),
);
}
+ /**
+ * Check if the current user is the Author of the entry
+ * @param $entry - the entry to be checked
+ * @param $rules - the rules applying to this section
+ * @return boolean
+ */
+ private function superseedsPermissions(){
+ return Symphony::Author()->isDeveloper() || (Symphony::Author()->isManager() && Symphony::Configuration()->get('manager', 'author_roles') === 'yes');
+ }
+
+ /**
+ * Check if the current user is the Author of the entry
+ * @param $entry - the entry to be checked
+ * @param $rules - the rules applying to this section
+ * @return boolean
+ */
+ private function isOwnEntry($entry,$rules){
+ $sectionId = $entry->get('section_id');
+
+ $authorId = Symphony::Author()->get('id');
+ $authorName = Symphony::Author()->get('first_name') . ' ' . Symphony::Author()->get('last_name');
+
+ $canAccess = true;
+
+ $fieldId = FieldManager::fetchFieldIDFromElementName((string)Symphony::Configuration()->get('author_field', 'author_roles'),$sectionId);
+ // $field = FieldManager::fetch($fieldId);
+
+ $fieldType = FieldManager::fetchFieldTypeFromID($fieldId);
+
+ if ($field){
+
+ $fieldData = $entry->getData($fieldId);
+
+ if ($fieldType == 'author'){
+ //use symphony author
+ $canAccess = ($fieldData['author_id'] == $authorId);
+ } else {
+ $fieldValue = $fieldData['value'];
+ if (!is_array($fieldValue)){
+ $fieldValue = array($fieldValue);
+ }
+ $fieldValue = array_map('strtolower', $fieldValue);
+
+ if ( in_array(strtolower($authorName), $fieldValue)){
+ $canAccess = true;
+ } else {
+ $canAccess = false;
+ }
+ }
+ } else {
+ //use symphony author
+ $canAccess = ($entry->get('author_id') == $authorId);
+ }
+
+ return $canAccess;
+ }
+
+ /**
+ * Check if the rules permit or deny access to the entry id
+ * @param $entryId - the entry id to be checked
+ * @param $rules - the rules applying to this section
+ * @return boolean
+ */
+ private function filterCanAccess($entryId,$rules){
+ $rule = explode(':', $rules['filter_rule']);
+
+ $canAccess = true;
+
+ if(count($rule) == 2) {
+ // Valid filter, now get the ID's:
+ $filteredIDs = array();
+ $action = $rule[0];
+ $idsArr = explode(',', $rule[1]);
+
+ foreach($idsArr as $idExpr) {
+ $a = explode('-', trim($idExpr));
+
+ if(count($a)==1) {
+ // Regular ID
+ $filteredIDs[] = $a[0];
+ }
+ elseif(count($a)==2) {
+ // Range
+ $from = $a[0];
+ $to = $a[1];
+
+ if($to >= $from) {
+ for($i = $from; $i <= $to; $i++){
+ $filteredIDs[] = $i;
+ }
+ }
+ }
+ }
+
+ switch($action) {
+ case 'show' :
+ // Only show the given ids.
+ if ( in_array($entryId, $filteredIDs)){
+ $canAccess = true;
+ } else {
+ $canAccess = false;
+ }
+ break;
+ case 'hide' :
+ // Only show entries which do not have the given ids.
+ if ( !in_array($entryId, $filteredIDs)){
+ $canAccess = true;
+ } else {
+ $canAccess = false;
+ }
+ break;
+ }
+ }
+
+ return $canAccess;
+ }
+
+ /**
+ * Check that the current user has access prior to deleting an entry
+ */
+ public function entryPreDelete($context) {
+ $data = $this->getCurrentAuthorRoleData();
+
+ if($data == false || $this->superseedsPermissions()) {
+ return;
+ }
+
+ $section = Symphony::Engine()->getPageCallback()['context']['section_handle'];
+
+ foreach($data['sections'] as $id_section => $rules) {
+ if($rules['handle'] == $section) {
+
+ $canAccess = true;
+
+ if($rules['delete'] == 0) {
+ $canAccess = false;
+ }
+
+ if ( !$canAccess ){
+ //throw custom error if access to entry is not allowed
+ Administration::instance()->throwCustomError(
+ __('Restricted Access'),
+ __('You are not allowed to delete entries in this section'),
+ Page::HTTP_STATUS_NOT_FOUND
+ );
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that the current user has access prior to showing creating an entry
+ */
+ public function entryPreCreate($context) {
+
+ $data = $this->getCurrentAuthorRoleData();
+
+ if($data == false || $this->superseedsPermissions()) {
+ return;
+ }
+
+ $section = Symphony::Engine()->getPageCallback()['context']['section_handle'];
+
+ foreach($data['sections'] as $id_section => $rules) {
+ if($rules['handle'] == $section) {
+
+ $canAccess = true;
+
+ if($rules['create'] == 0) {
+ $canAccess = false;
+ }
+
+ if ( !$canAccess ){
+ //throw custom error if access to entry is not allowed
+ Administration::instance()->throwCustomError(
+ __('Restricted Access'),
+ __('You are not allowed to create entries in this section'),
+ Page::HTTP_STATUS_NOT_FOUND
+ );
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Check that the current user has access prior to saving entry edits
+ */
+ public function entryPreEdit($context) {
+
+ $data = $this->getCurrentAuthorRoleData();
+
+ if($data == false || $this->superseedsPermissions()) {
+ return;
+ }
+
+ $section = Symphony::Engine()->getPageCallback()['context']['section_handle'];
+
+ foreach($data['sections'] as $id_section => $rules) {
+ if($rules['handle'] == $section) {
+
+ $canAccess = true;
+
+ if($rules['edit'] == 0) {
+ $canAccess = false;
+ }
+
+ if($rules['edit_own_entries'] == 1 && $canAccess) {
+ $canAccess = $this->isOwnEntry($context['entry'],$rules);
+ }
+
+ // Add or remove ID's from the filter:
+ if($rules['use_filter'] == 1 && $canAccess) {
+ $canAccess = $this->filterCanAccess($context['entry']->get('id'),$rules);
+ }
+
+ if ( !$canAccess ){
+ //throw custom error if access to entry is not allowed
+ Administration::instance()->throwCustomError(
+ __('Restricted Access'),
+ __('You do not have permissions to edit entry %s.', array($context['entry']->get('id'))),
+ Page::HTTP_STATUS_NOT_FOUND
+ );
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Check that the current user has view or edit access prior to showing the entry edit screen
+ */
+ public function entryPreRender($context) {
+
+ $data = $this->getCurrentAuthorRoleData();
+
+ if($data == false || $this->superseedsPermissions()) {
+ return;
+ }
+
+ $section = Symphony::Engine()->getPageCallback()['context']['section_handle'];
+
+ foreach($data['sections'] as $id_section => $rules) {
+ if($rules['handle'] == $section) {
+
+ $canAccess = true;
+
+ if($rules['visible'] == 0 && $rules['edit'] == 0) {
+ $canAccess = false;
+ }
+
+ if($rules['view_own_entries'] == 1 && $canAccess) {
+ $canAccess = $this->isOwnEntry($context['entry'],$rules);
+ }
+
+ // Add or remove ID's from the filter:
+ if($rules['use_filter'] == 1 && $canAccess) {
+ $canAccess = $this->filterCanAccess($context['entry']->get('id'),$rules);
+ }
+
+ if ( !$canAccess ){
+ //throw custom error if access to entry is not allowed
+ Administration::instance()->throwCustomError(
+ __('Unknown Entry'),
+ __('The Entry, %s, could not be found.', array($context['entry']->get('id'))),
+ Page::HTTP_STATUS_NOT_FOUND
+ );
+ }
+ }
+
+ }
+ // var_dump($context);die;
+ }
+
+ /**
+ * Ensure that any required filtering is done to show only entries which the user has access to in the list views
+ */
+ public function adjustPublishFiltering($context) {
+ // var_dump($context);die;
+
+ $authorId = Symphony::Author()->get('id');
+ $authorName = Symphony::Author()->get('first_name') . ' ' . Symphony::Author()->get('last_name');
+
+ $data = $this->getCurrentAuthorRoleData();
+
+ if($data == false || $this->superseedsPermissions()) {
+ return;
+ }
+
+ $section = Symphony::Engine()->getPageCallback()['context']['section_handle'];
+
+ foreach($data['sections'] as $id_section => $rules) {
+ if($rules['handle'] == $section) {
+
+ if($rules['visible'] == 0) {
+ Administration::instance()->throwCustomError(
+ __('Unknown Section'),
+ __('The Section, %s, could not be found.', array($section)),
+ Page::HTTP_STATUS_NOT_FOUND
+ );
+ }
+
+ if($rules['view_own_entries'] == 1) {
+ // Only get the ID's of the current author to begin with:
+
+ //if section has field Author -- defined by config
+ // $sectionObject = SectionManager::fetch($id_section);
+
+ $fieldId = FieldManager::fetchFieldIDFromElementName((string)Symphony::Configuration()->get('author_field', 'author_roles'),$id_section);
+ $field = FieldManager::fetch($fieldId);
+
+ $fieldType = FieldManager::fetchFieldTypeFromID($fieldId);
+
+ if ($field){
+ $context['joins'] .= " LEFT JOIN `tbl_entries_data_{$fieldId}` as `a{$fieldId}` on `e`.`id` = `a{$fieldId}`.`entry_id` ";
+ if ($fieldType == 'author'){
+ //use symphony author
+ $context['where'] .= " AND `a{$fieldId}`.`author_id` = '{$authorId}'";
+ } else {
+ $context['where'] .= " AND `a{$fieldId}`.`value` = '{$authorName}'";
+ }
+ } else {
+ //use symphony author
+ $context['where'] .= " AND `e`.`author_id` = '{$authorId}'";
+ }
+ // $results = Symphony::Database()->fetch('SELECT `id` FROM `tbl_entries` WHERE `author_id`');
+ }
+
+
+ // Add or remove ID's from the filter:
+ if($rules['use_filter'] == 1) {
+ $rule = explode(':', $rules['filter_rule']);
+
+ if(count($rule) == 2) {
+ // Valid filter, now get the ID's:
+ $filteredIDs = array();
+ $action = $rule[0];
+ $idsArr = explode(',', $rule[1]);
+
+ foreach($idsArr as $idExpr) {
+ $a = explode('-', trim($idExpr));
+
+ if(count($a)==1) {
+ // Regular ID
+ $filteredIDs[] = $a[0];
+ }
+ elseif(count($a)==2) {
+ // Range
+ $from = $a[0];
+ $to = $a[1];
+
+ if($to >= $from) {
+ for($i = $from; $i <= $to; $i++){
+ $filteredIDs[] = $i;
+ }
+ }
+ }
+ }
+
+ $filteredIDs = MySQL::cleanValue(implode(',',$filteredIDs));
+
+ switch($action) {
+ case 'show' :
+ // Only show the given ids.
+ $context['where'] .= " AND `e`.`id` IN ('{$filteredIDs}')";
+ break;
+ case 'hide' :
+ // Only show entries which do not have the given ids.
+ $context['where'] .= " AND `e`.`id` NOT IN ('{$filteredIDs}')";
+ break;
+ }
+ }
+ }
+
+
+
+ }
+ }
+ }
+
+ /**
+ * Add Author Roles Navigation Items
+ */
public function fetchNavigation() {
return array(
array(
@@ -79,7 +474,7 @@ public function fetchNavigation() {
public function extendNavigation($context) {
$data = $this->getCurrentAuthorRoleData();
- if($data == false || Administration::instance()->Author->isDeveloper()) {
+ if($data == false || $this->superseedsPermissions()) {
return;
}
@@ -153,7 +548,7 @@ public function deleteAuthorRole($context) {
* The context, providing the form and the author object
*/
public function addRolePicker($context) {
- if(Administration::instance()->Author->isDeveloper()) {
+ if($this->superseedsPermissions()) {
$group = new XMLElement('fieldset');
$group->setAttribute('class', 'settings');
$group->appendChild(new XMLElement('legend', __('Author Role')));
@@ -230,9 +625,11 @@ public function checkCallback($context) {
* @return mixed
*/
private function adjustIndex($context, $callback) {
+
+
$data = $this->getCurrentAuthorRoleData();
- if($data == false || Administration::instance()->Author->isDeveloper()) {
+ if($data == false || $this->superseedsPermissions()) {
return;
}
@@ -253,196 +650,16 @@ private function adjustIndex($context, $callback) {
// Check if there are rules:
if($rules['create'] == 0) {
// It is not allowed to create new items:
- $children = current($context['oPage']->Context->getChildrenByName('ul'))->getChildrenByName('li');
+ $topMenu = current($context['oPage']->Context->getChildrenByName('ul'));
+ $children = $topMenu->getChildrenByName('li');
foreach($children as $key => $child) {
- if(strpos($child->getValue(),__('Create New')) !== false) {
- $value = $child->getValue();
- $child->setValue(''.strip_tags(str_replace(__('Create New'), '', $value)).'');
+ var_dump($child->getValue()->getValue());
+ if(strpos($child->getValue()->getValue(),__('Create New')) !== false) {
+ $topMenu->removeChildAt($key);
}
}
}
-
- if($rules['own_entries'] == 1 || $rules['edit'] == 0 || $rules['delete'] == 0 || $rules['use_filter'] == 1) {
- // For only show entries created by this author:
- // Get a list of entry id's created by this author:
- $id_author = Administration::instance()->Author->get('id');
-
- if($rules['own_entries'] == 1) {
- // Only get the ID's of the current author to begin with:
- $results = Symphony::Database()->fetch('SELECT `id` FROM `tbl_entries` WHERE `author_id` = '.$id_author.';');
- }
- else {
- // Get all the ID's:
- $results = Symphony::Database()->fetch('SELECT `id` FROM `tbl_entries`;');
- }
-
- $ids = array();
-
- foreach($results as $result)
- {
- $ids[] = $result['id'];
- }
-
- // Add or remove ID's from the filter:
- if($rules['use_filter'] == 1) {
- $rule = explode(':', $rules['filter_rule']);
-
- if(count($rule) == 2) {
- // Valid filter, now get the ID's:
- $filteredIDs = array();
- $action = $rule[0];
- $idsArr = explode(',', $rule[1]);
-
- foreach($idsArr as $idExpr) {
- $a = explode('-', trim($idExpr));
-
- if(count($a)==1) {
- // Regular ID
- $filteredIDs[] = $a[0];
- }
- elseif(count($a)==2) {
- // Range
- $from = $a[0];
- $to = $a[1];
-
- if($to >= $from) {
- for($i = $from; $i <= $to; $i++){
- $filteredIDs[] = $i;
- }
- }
- }
- }
-
- switch($action) {
- case 'show' :
- // Only show the given ids. Well that's easy:
- $ids = $filteredIDs;
- break;
- case 'hide' :
- // Remove the filtered ids from the ids-array:
- $ids = array_diff($ids, $filteredIDs);
- break;
- }
- }
- }
-
- // Now, check each table row:
- $newContents = new XMLElement('div', null, $context['oPage']->Contents->getAttributes());
-
- foreach($context['oPage']->Contents->getChildren() as $contentsChild) {
- if($contentsChild->getName() == 'form') {
- $newForm = new XMLElement('form', null, $contentsChild->getAttributes());
-
- foreach($contentsChild->getChildren() as $formChild) {
- // only show entries created by this author, or which are allowed by the filter:
- if($formChild->getName() == 'table' && ($rules['own_entries'] == 1 || $rules['use_filter'] == 1)) {
- $newTable = new XMLElement('table', null, $formChild->getAttributes());
-
- foreach($formChild->getChildren() as $tableChild) {
- if($tableChild->getName() == 'tbody') {
- $newTableBody = new XMLElement('tbody', null, $tableChild->getAttributes());
-
- foreach($tableChild->getChildren() as $tableRow) {
- // Check the ID:
- $id = explode('-', $tableRow->getAttribute('id'));
-
- if(in_array($id[1], $ids)) {
- $newTableBody->appendChild($tableRow);
- }
- }
-
- $newTable->appendChild($newTableBody);
- }
- else {
- $newTable->appendChild($tableChild);
- }
- }
-
- $newForm->appendChild($newTable);
- }
- elseif($formChild->getName() == 'div' && $formChild->getAttribute('class') == 'actions') {
- // Only proceed if you can either edit or delete. Otherwise it would have much sense to have an apply-button here...
- if($rules['delete'] == 1 || $rules['edit'] == 1) {
- $child = self::findChildren($formChild,'select');
- $child = $child[0];
-
- $newSelect = new XMLElement('select', null, $child->getAttributes());
-
- foreach($child->getChildren() as $selectChild) {
- // See if delete is allowed:
- if($selectChild->getAttribute('value') == 'delete' && $rules['delete'] == 1) {
- $newSelect->appendChild($selectChild);
- }
- elseif($selectChild->getName() == 'optgroup' && $rules['edit'] == 1) {
- // Check if the field that is edited is not a hidden field, because then editing is not allowed:
- $optGroupChildren = $selectChild->getChildren();
-
- if(!empty($optGroupChildren)) {
- $value = $optGroupChildren[0]->getAttribute('value');
-
- $a = explode('-', str_replace('toggle-', '', $value));
-
- if(!in_array($a[0], $hiddenFields)) {
- $newSelect->appendChild($selectChild);
- }
- }
- }
- elseif($selectChild->getName() == 'option' && $selectChild->getAttribute('value') != 'delete' && ($rules['edit'] == 1 || $rules['delete'] == 1)) {
- $newSelect->appendChild($selectChild);
- }
- }
-
- // if the new select has only one entry,
- // it is the dummy entry and we can discard it
- if($newSelect->getNumberOfChildren() > 1 ) {
- self::replaceChild($formChild, $newSelect);
- $newForm->appendChild($formChild);
- }
- }
- }
- else {
- $newForm->appendChild($formChild);
- }
- }
-
- $newContents->appendChild($newForm);
- $context['oPage']->Form = $newForm;
- }
- else {
- $newContents->appendChild($contentsChild);
- }
- }
-
- $context['oPage']->Contents = $newContents;
- }
- }
- }
- }
-
- /**
- * See if there should be made some adjustments to the current page:
- * @param $context
- * The context
- */
- public function makePreAdjustements($context) {
- $data = $this->getCurrentAuthorRoleData();
-
- if($data == false || Administration::instance()->Author->isDeveloper()) {
- return;
- }
-
- // Check if something needs to be done before anything is done:
- $callback = Symphony::Engine()->getPageCallback();
-
- // If the user is only allowed to see his or her own entries, then the configuration should be overwritten to a maximum.
- if($callback['driver'] == 'publish' && $callback['context']['page'] == 'index') {
- $section = $callback['context']['section_handle'];
-
- foreach($data['sections'] as $id_section => $rules) {
- if($rules['handle'] == $section && $rules['own_entries'] == 1) {
- Symphony::Configuration()->set('pagination_maximum_rows', PHP_INT_MAX, 'symphony');
- }
}
}
}
@@ -456,7 +673,11 @@ private static function findChildren($element, $names) {
$children = array();
- foreach($element->getChildren() as $child) {
+ if (!is_object($element)){
+ return $children;
+ }
+
+ foreach($element->getIterator() as $child) {
$children = array_merge($children, self::findChildren($child,$names));
if(in_array($child->getName(), $names )) {
@@ -471,7 +692,7 @@ private static function findChildren($element, $names) {
// name matches the name of the second argument with
// the second argument
private static function replaceChild($parent, $child) {
- foreach($parent->getChildren() as $position => $oldChild) {
+ foreach($parent->getIterator() as $position => $oldChild) {
if($oldChild->getName() == $child->getName()) {
$parent->replaceChildAt($position,$child);
@@ -493,7 +714,7 @@ private static function replaceChild($parent, $child) {
private function adjustEntryEditor($context, $callback) {
$data = $this->getCurrentAuthorRoleData();
- if($data == false || Administration::instance()->Author->isDeveloper()) {
+ if($data == false || $this->superseedsPermissions()) {
return;
}
@@ -549,12 +770,6 @@ private function adjustEntryEditor($context, $callback) {
}
}
else {
- if($rules['edit'] == 0) {
- foreach(self::findChildren($formChild,'input,select,textarea') as $child) {
- $child->setAttribute('disabled','disabled');
- }
- }
-
$newForm->appendChild($formChild);
}
}
@@ -580,7 +795,7 @@ private function adjustEntryEditor($context, $callback) {
*/
private function getCurrentAuthorRoleData() {
if(Administration::instance()->isLoggedIn()) {
- $id_author = Administration::instance()->Author->get('id');
+ $id_author = Symphony::Author()->get('id');
$id_role = $this->getAuthorRole($id_author);
if($id_role != false) {
@@ -601,7 +816,7 @@ private function getCurrentAuthorRoleData() {
public function modifyAreas($context) {
$data = $this->getCurrentAuthorRoleData();
- if($data == false || Administration::instance()->Author->isDeveloper()) {
+ if($data == false || $this->superseedsPermissions()) {
return;
}
@@ -622,7 +837,7 @@ public function modifyAreas($context) {
* The context
*/
public function saveAuthorRole($context) {
- if(Administration::instance()->Author->isDeveloper()) {
+ if($this->superseedsPermissions()) {
$id_role = intval($_POST['fields']['role']);
$id_author = $context['author']->get('id');
@@ -715,7 +930,8 @@ public function getData($id_role) {
A.`create`,
A.`edit`,
A.`delete`,
- A.`own_entries`,
+ A.`view_own_entries`,
+ A.`edit_own_entries`,
A.`use_filter`,
A.`filter_rule`
FROM
@@ -806,7 +1022,8 @@ public function saveData($values) {
$insert['create'] = isset($info['create']) ? 1 : 0;
$insert['edit'] = isset($info['edit']) ? 1 : 0;
$insert['delete'] = isset($info['delete']) ? 1 : 0;
- $insert['own_entries'] = isset($info['own_entries']) ? 1 : 0;
+ $insert['view_own_entries'] = isset($info['view_own_entries']) ? 1 : 0;
+ $insert['edit_own_entries'] = isset($info['edit_own_entries']) ? 1 : 0;
$insert['use_filter'] = isset($info['use_filter']) ? 1 : 0;
// Filter rule:
@@ -833,10 +1050,42 @@ public function saveData($values) {
}
}
+ public function appendPreferences($context){
+ $group = new XMLElement('fieldset',null,array('class'=>'settings'));
+ $group->appendChild(new XMLElement('legend', 'Author Roles'));
+
+
+ $div = new XMLElement('div',null,array('class'=>'group'));
+ $label = Widget::Label();
+ $input = Widget::Input("settings[author_roles][author_field]", (string)Symphony::Configuration()->get('author_field', 'author_roles'), 'text');
+ $label->setValue(__('Author Field Handle') . $input->generate());
+ $div->appendChild($label);
+ $div->appendChild(new XMLElement('p','Provide an `author` field handle which is used to detect the author instead of creator of the Symphony entry.',array('class'=>'help')));
+
+ $group->appendChild($div);
+
+
+ // Append settings
+ $label = Widget::Label();
+ $input = Widget::Input('settings[author_roles][manager]', 'yes', 'checkbox');
+
+ if (Symphony::Configuration()->get('manager', 'author_roles') === 'yes') {
+ $input->setAttribute('checked', 'checked');
+ }
+
+ $label->setValue($input->generate() . ' ' . __('Managers should not have restricted access and can set permissions'));
+ $group->appendChild($label);
+
+ // Append preferences
+ $context['wrapper']->appendChild($group);
+ }
+
/**
* Installation
*/
public function install() {
+ Symphony::Configuration()->set('manager', 'yes', 'author_roles');
+
// Roles table:
Symphony::Database()->query("
CREATE TABLE IF NOT EXISTS `tbl_author_roles` (
@@ -869,7 +1118,8 @@ public function install() {
`create` TINYINT(1) unsigned NOT NULL,
`edit` TINYINT(1) unsigned NOT NULL,
`delete` TINYINT(1) unsigned NOT NULL,
- `own_entries` TINYINT(1) unsigned NOT NULL,
+ `view_own_entries` TINYINT(1) unsigned NOT NULL,
+ `edit_own_entries` TINYINT(1) unsigned NOT NULL,
`use_filter` TINYINT(1) unsigned NOT NULL,
`filter_rule` TEXT NOT NULL,
PRIMARY KEY (`id`),
@@ -909,11 +1159,21 @@ public function uninstall() {
* The version that is currently installed in this Symphony installation
* @return boolean
*/
- public function update($previousVersion) {
+ public function update($previousVersion = false) {
if(version_compare($previousVersion, '1.2', '<')) {
// Update from pre-1.1 to 1.2:
return Symphony::Database()->query('ALTER TABLE `tbl_author_roles` ADD `custom_elements` TEXT NULL;');
}
+ if(version_compare($previousVersion, '2.0', '<')) {
+ // Update from pre-2.0 to 2.0
+ Symphony::Configuration()->set('manager', 'yes', 'author_roles');
+
+ return Symphony::Database()->query("
+ ALTER TABLE `tbl_author_roles_sections` ADD `edit_own_entries` TINYINT(1) unsigned NOT NULL;
+ UPDATE `tbl_author_roles_sections` SET `edit_own_entries` = `own_entries`;
+ ALTER TABLE `tbl_author_roles_sections` CHANGE `own_entries` `view_own_entries` TINYINT(1) unsigned NOT NULL;
+ ");
+ }
}
}
diff --git a/extension.meta.xml b/extension.meta.xml
index 0e2920b..19ec2b9 100644
--- a/extension.meta.xml
+++ b/extension.meta.xml
@@ -11,15 +11,36 @@
Twisted Interactive
http://www.twisted.nl
+
+ Maze Digital
+ http://maze.digital
+ jon@maze.digital
+
-
+
Added functionality to hide menu elements created by other extensions. __Important:__ Since extensions can
not (yet) influence the execution order of extensions in Symphony, you need to apply a tiny little 'hack'
to Symphony to make sure the 'Author Roles'-extension is executed as last, after all other extensions have
made their possible modifications to the navigation. Read the readme for more details.
+
+ Updated compatibility for Symphony 2.5
+
+
+ Re Written Core Access Functionality
+ - Table view now uses filters to narrow down user permissions
+ - Entry edit now checks that the user has view/edit permissions before loading the page
+ - User is given an entry/section not found if they are not allowed to view/edit the said entry/section
+ - Similar Errors are thrown when trying to create, edit and delete entries without the necessary permissions
+ - Added ability to use custom field to determine Author
+ - Author field uses the author id
+ - All other fields match the author name with the value
+ - Author field name has to be consistent across all sections
+ - Differenciated in between Viewing and Editing own entries, one can now view all but only edit own entries
+ - Added ability to allow Managers to set and have full permissions
+
diff --git a/readme.md b/readme.md
index 71656c8..a838227 100644
--- a/readme.md
+++ b/readme.md
@@ -3,10 +3,13 @@
Author: Twisted Interactive
Website: http://www.twisted.nl
+Mantained by: Maze Digital
+Website: http://maze.digital
+
## What does this extension do? ##
In short: this extension allows you to set permissions for each author with roles.
-It is the successor of the [Author Section extension](https://github.com/kanduvisla/author_section).
+It is the successor of the Author Section extension
More detailed: The extension allows you to set the following permissions:
@@ -43,8 +46,12 @@ you're safe now, otherwise you have to go into the database, look for the `tbl_e
ID to be the highest number in the table. Don't change the other extensions! After that, edit the `tbl_extensions_delegates`-table
and change the rows which have `extension_id` set to the old ID, and update them to the new ID. Now everything should work just fine!
+### Symphony 3.0
+
+The above hack would no longer be necessary once Symphony 3.0 is released as a [custom order](https://github.com/symphonycms/symphony-2/commit/e6dd9d4611a5a153b1d657e3418b5d34ef381d43) is allowed when setting delegates. If you feel brave you can merge this commit with your install, and make sure that the `tbl_extensions_delegates` table has the new order field. You will still have to 'set' the order value manually in the database but no need to hack the core.
+
## Sidenotes ##
- Fields that are set to 'hidden' will be made hidden with JavaScript. This is to ensure that all the data gets send and stored on a POST-action when an entry is saved. However, this could cause some issues with third-party field-types, although these aren't encountered yet.
- Fields that are required cannot be set to 'hidden', since that would cause an error when trying to store the entry.
-- If you choose to filter entries (by letting an author only show his/her own entries or using the filter), pagination on the publish pages is disabled. This has to be done, because Symphony doesn't have a hook to alter the query used to retreive the entries.
+- Relationships using SBL/Association Field etc are not 'filtered' in this version. So a User can view all entries when linking. Editing entries would still work as per the settings provided to the Author roles. Do not use relationships if you don't want users to see certain related entries.