Skip to content

Instantly share code, notes, and snippets.

@mfairchild365
Created September 15, 2011 02:55
Show Gist options
  • Save mfairchild365/1218408 to your computer and use it in GitHub Desktop.
Save mfairchild365/1218408 to your computer and use it in GitHub Desktop.
auto load objects and check permissions.
<?php
class Example_Account_Record extends Example_Editable
{
public $email;
public $password;
public $first_name;
public $last_name;
public $employee_id;
public $status;
public $location_id;
public $timezone;
public function getPermissionableClass()
{
return __CLASS__;
}
public static function getByID($id)
{
return self::getByAnyField('Example_Account_Record', 'id', (int)$id);
}
function keys()
{
return array('id');
}
public static function getTable()
{
return 'accounts';
}
}
<?php
class Example_ACL
{
public static function getActionValue($actionString)
{
switch ($actionString)
{
case 'none':
return 0;
break;
case 'view':
return 1;
break;
case 'create':
return 2;
break;
case 'edit':
return 3;
break;
case 'status':
return 4;
break;
case 'delete':
return 5;
break;
default:
throw new Exception("Unknown Action", 500);
}
}
public static function isAllowed(Example_Account_Record $user, $object, $action)
{
if (!in_array('Example_Permissionable', class_implements($object))) {
throw new Exception('That class is not permissionable', 500);
}
$action = self::getActionValue($action);
$method = "getNonOwnerPermission";
if ($user->id == $object->owner_id) {
$method= "getOwnerPermission";
}
$permission = 0;
foreach($user->getGroups() as $group) {
if ($groupPermission = $group->$method($object->getPermissionableClass(), $object->getScope($user)) >= $action) {
return true;
}
}
return false;
}
}
abstract class Example_Editable extends Example_PermissionableRecord
{
//Require these for every Br_Editable class.
public $id;
public $date_created;
public $date_edited;
public $owner_id;
public $creator_id;
function __construct($options = array())
{
//Check to see if we are editing this bro.
if (isset($options['model']) && get_called_class() != $options['model']) {
//We are not viewing this model, return.
return;
}
//An Id was not passed, so we are just making a new one.
if (!isset($options['id'])) {
return;
}
if (!$class = $this->getByID($options['id'])) {
throw new Exception("Could not find that", 400);
}
$this->synchronizeWithArray($class->toArray());
if (!Example_ACL::isAllowed(Br_Controller::getAccount(), $this, 'view')) {
throw new Exception("You do not have permission to view this object", 401);
}
if (isset($options['model']) && substr($options['model'], -5) != '_Edit') {
//We are not viewing the Edit model for this class, return.
return;
}
if (!Example_ACL::isAllowed(Br_Controller::getAccount(), $this, 'edit')) {
throw new Exception("You do not have permission to edit this.", 401);
}
}
}
@mfairchild365
Copy link
Author

When using this is combination with the RegExpRouter you can load your optional class by passing along the $options['model']. When we construct an editable record, we check to see if we are viewing the same model. If we are we continue on to load that model based on the $options['id']. Then we check permissions to see if we are able to view it... etc.

This method allows us to reduce the redundant constructors that consist of:
function __construct()
{
if (isset($options['id']) {
//load this class with that id.
}

//check permissions.
}

Just an idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment