Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
83.33% |
5 / 6 |
CRAP | |
91.67% |
22 / 24 |
Friend | |
0.00% |
0 / 1 |
|
83.33% |
5 / 6 |
14.11 | |
91.67% |
22 / 24 |
__construct | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
__get | |
100.00% |
1 / 1 |
3 | |
100.00% |
5 / 5 |
|||
__isset | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
__set | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
__call | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
_get_property | |
0.00% |
0 / 1 |
3.58 | |
60.00% |
3 / 5 |
<?php declare(strict_types=1); | |
/** | |
* Ion | |
* | |
* Building blocks for web development | |
* | |
* PHP version 7.2 | |
* | |
* @package Ion | |
* @author Timothy J. Warren <tim@timshomepage.net> | |
* @copyright 2015 - 2019 Timothy J. Warren | |
* @license http://www.opensource.org/licenses/mit-license.html MIT License | |
* @version 3.0.0 | |
* @link https://git.timshomepage.net/aviat/ion | |
*/ | |
namespace Aviat\Ion; | |
use BadMethodCallException; | |
use InvalidArgumentException; | |
use ReflectionClass; | |
use ReflectionMethod; | |
use ReflectionProperty; | |
/** | |
* Friend class for testing | |
*/ | |
class Friend { | |
/** | |
* Object to create a friend of | |
* @var mixed | |
*/ | |
private $_friend_; | |
/** | |
* Reflection class of the object | |
* @var ReflectionClass | |
*/ | |
private $_reflect_; | |
/** | |
* Create a friend object | |
* | |
* @param mixed $obj | |
* @throws InvalidArgumentException | |
* @throws \ReflectionException | |
*/ | |
public function __construct($obj) | |
{ | |
if ( ! \is_object($obj)) | |
{ | |
throw new InvalidArgumentException('Friend must be an object'); | |
} | |
$this->_friend_ = $obj; | |
$this->_reflect_ = new ReflectionClass($obj); | |
} | |
/** | |
* Retrieve a friend's property | |
* | |
* @param string $key | |
* @return mixed | |
*/ | |
public function __get(string $key) | |
{ | |
if ($this->__isset($key)) | |
{ | |
$property = $this->_get_property($key); | |
if ($property !== NULL) | |
{ | |
return $property->getValue($this->_friend_); | |
} | |
} | |
return NULL; | |
} | |
/** | |
* See if a property exists on the friend | |
* | |
* @param string $name | |
* @return bool | |
*/ | |
public function __isset(string $name): bool | |
{ | |
return $this->_reflect_->hasProperty($name); | |
} | |
/** | |
* Set a friend's property | |
* | |
* @param string $key | |
* @param mixed $value | |
* @return void | |
*/ | |
public function __set(string $key, $value) | |
{ | |
if ($this->__isset($key)) | |
{ | |
$property = $this->_get_property($key); | |
if ($property !== NULL) | |
{ | |
$property->setValue($this->_friend_, $value); | |
} | |
} | |
} | |
/** | |
* Calls a protected or private method on the friend | |
* | |
* @param string $method | |
* @param array $args | |
* @return mixed | |
* @throws BadMethodCallException | |
* @throws \ReflectionException | |
*/ | |
public function __call(string $method, array $args) | |
{ | |
if ( ! $this->_reflect_->hasMethod($method)) | |
{ | |
throw new BadMethodCallException("Method '{$method}' does not exist"); | |
} | |
$friendMethod = new ReflectionMethod($this->_friend_, $method); | |
$friendMethod->setAccessible(TRUE); | |
return $friendMethod->invokeArgs($this->_friend_, $args); | |
} | |
/** | |
* Iterates over parent classes to get a ReflectionProperty | |
* | |
* @param string $name | |
* @return ReflectionProperty|null | |
*/ | |
private function _get_property(string $name): ?ReflectionProperty | |
{ | |
try | |
{ | |
$property = $this->_reflect_->getProperty($name); | |
$property->setAccessible(TRUE); | |
return $property; | |
} | |
// Return NULL on any exception, so no further logic needed | |
// in the catch block | |
catch (\Exception $e) | |
{ | |
return NULL; | |
} | |
} | |
} | |
// End of Friend.php |