<?php
namespace Phad;
trait Can_Do {
public $force_allow_access = false;
/**
* Check an access string.
* @alias can_access just to make it easier to simply check a string
*
* @param string a string like 'role:admin;call:whatever;'
* @param $ItemInfo optional array of ItemInfo from a compiled phad item
*
* @return true/false
*
* @throws exception if a function is not defined.
*/
public function can(string $function, $ItemInfo=null){
return $this->can_access(['access'=>$function], $ItemInfo);
}
/**
* Check if an individual row can be read. This is ONLY called when getting an item's rows, NOT when displaying an item's view.
*
* @param $ItemRow the data being accessed
* @param $ItemInfo info info about the item
* @param $ItemName ... the item's name
*
* @return true
* @override to fine-tune row access
* @todo allow this to be specified on the item's node
*/
public function can_read_row(array $ItemRow,object $ItemInfo,string $Item){
if (isset($this->handlers['can_read_row'])){
return ($this->handlers['can_read_row'])($ItemRow,$ItemInfo,$Item);
}
// echo 'here';exit;
return true;
}
/**
* @param $node array of the node's attributes & it's tagName
*/
public function can_read_node(array $node){
if (!isset($node['access'])){return true;}
return $this->can_access($node);
}
/**
* Checks if the data node can be accessed.
*
* @param $node the data node (as an array)
* @param $Info item info object
* @return true/false
*/
public function can_read_data(array $node, \stdClass $Info){
if ($Info->mode==\Phad\Blocks::FORM_SUBMIT&&$node['type']!='default')return false;
//@deprecated in favor of EPERIMENTAL `:data` arg checked inside the compiled view
if (isset($Info->args['data.name'])&&(!isset($node['name'])||$Info->args['data.name']!=$node['name']))return false;
if (!isset($node['access'])){
return true;
}
return $this->can_access($node);
}
/**
* Check an access string
*
* @param array $node a nodeinfo array containing a key 'access' with a string like 'role:admin;call:whatever;'
* @param $ItemInfo optional array of ItemInfo from a compiled phad item
*
* @return true/false
*
* @throws exception if a function is not defined.
*/
public function can_access(array $node, $ItemInfo=null){
$access_string = $node['access'];
$functions = $this->parse_functions($access_string);
if ($this->force_allow_access === true)return true;
foreach ($functions as $fn=>/*string*/$arg){
// var_dump("Function:".$fn);
if ($fn=='role'){
if (!$this->user_has_role($arg))return false;
} else if ($fn=='request_method'){
if (strtolower($_SERVER['REQUEST_METHOD'])!=strtolower($arg))return false;
} else if ($fn=='call'){
//@todo append to `$Info->errors[]` ??
if($this->call($arg, $node, $ItemInfo)!==true)return false;
} else {
// @todo instead of exception, add to errors list ??
throw new \Exception("Function '$fn' does not exist. Arg was '$arg'");
}
}
return true;
}
public function can_delete($Info){
$candelete = $Info->candelete;
//@todo test the different branches for can_delete() & delete()
if (!isset($Info->args['id'])){
$Info->submit_errors[] = ['msg'=>"Cannot delete '".$Info->name."' without an id. No id was submitted."];
return false;
} else if ($candelete===true)return true;
else if ($candelete===false){
$Info->submit_errors[] = ['msg'=>"Deletion of '".$Info->name."' is disabled."];
return false;
}
$functions = $this->parse_functions($Info->candelete);
foreach ($functions as $fn=> /* string */ $args){
if ($fn=='role'){
if (!$this->user_has_role($args)){
$Info->submit_errors[] = ['msg'=>"Deletion of '".$Info->name."' not allowed unless you have role(s): '$args'"];
return false;
}
}
else if ($fn=='call'){
$count = count($Info->submit_errors);
$did_pass = $this->call($args, $Info);
if ($did_pass!==true){
if (count($Info->submit_errors)==$count){
$item_name = $Info->name;
$Info->submit_errors[] = ['msg'=>"Deleting '$item_name' rejected by '$fn:$args'"];
}
return false;
}
}
}
return true;
}
public function can_submit($Info, $ItemRow){
//@todo test the different branches for can_delete() & delete()
if (isset($Info->cancel_submit)&&$Info->cancel_submit === true){
// var_dump($Info->cansubmit);
return false;
}
$functions = $this->parse_functions($Info->cansubmit);
foreach ($functions as $fn=> /* string */ $args){
if ($fn=='role'){
if (!$this->user_has_role($args)){
$Info->submit_errors[] = ['msg'=>"Deletion of '".$Info->name."' not allowed unless you have role(s): '$arg'"];
return false;
}
}
else if ($fn=='call'){
$count = count($Info->submit_errors);
$did_pass = $this->call($args, $Info, $ItemRow);
if ($did_pass!==true){
if (count($Info->submit_errors)==$count){
$item_name = $Info->name;
$Info->submit_errors[] = ['msg'=>"Deleting '$item_name' rejected by '$fn:$args'"];
}
return false;
}
}
}
return true;
}
}