A field access is a joinpoint and can be intercepted by a field interceptor.
Наследование: extends Go\Aop\Intercept\Joinpoint
Пример #1
0
 /**
  * Method that should be called around property
  *
  * @param FieldAccess $property Joinpoint
  *
  * @Around("access(* Example->*)")
  * @return mixed
  */
 public function aroundFieldAccess(FieldAccess $property)
 {
     $type = $property->getAccessType() === FieldAccess::READ ? 'read' : 'write';
     $value = $property->proceed();
     echo "Calling Around Interceptor for field: ", get_class($property->getThis()), "->", $property->getField()->getName(), ", access: {$type}", ", value: ", json_encode($value), "<br>\n";
     return $value;
 }
Пример #2
0
 /**
  * Do the stuff you want to do before and after the
  * field is setted.
  *
  * @param FieldAccess $fieldWrite the joinpoint that corresponds to the field write
  * @return mixed the result of the field set {@link Joinpoint::proceed()}, might be intercepted by the
  * interceptor.
  */
 public function set(FieldAccess $fieldWrite)
 {
     $value = $fieldWrite->proceed();
     $adviceMethod = $this->adviceMethod;
     $adviceMethod($fieldWrite);
     return $value;
 }
 /**
  * Advice that controls an access to the properties
  *
  * @param FieldAccess $fieldAccess Joinpoint
  *
  * @Around("access(public|protected Demo\Example\PropertyDemo->*)")
  * @return mixed
  */
 public function aroundFieldAccess(FieldAccess $fieldAccess)
 {
     $value = $fieldAccess->proceed();
     echo "Calling Around Interceptor for ", $fieldAccess, ", value: ", json_encode($value), PHP_EOL;
     // $value = 666; You can change the return value for read/write operations in advice!
     return $value;
 }
 /**
  * Advice that controls an access to the properties
  *
  * @param FieldAccess $property Joinpoint
  *
  * @Around("access(* Demo\Example\PropertyDemo->*)")
  * @return mixed
  */
 public function aroundFieldAccess(FieldAccess $property)
 {
     $type = $property->getAccessType() === FieldAccess::READ ? 'read' : 'write';
     $value = $property->proceed();
     echo "Calling Around Interceptor for field: ", get_class($property->getThis()), "->", $property->getField()->getName(), ", access: {$type}", ", value: ", json_encode($value), PHP_EOL;
     // $value = 666; You can change the return value for read/write operations in advice!
     return $value;
 }
Пример #5
0
 /**
  * @Go\Before("access(public|protected **->*)")
  *
  * @param FieldAccess $access
  *
  * @return mixed
  */
 public function beforePropertyAccess(FieldAccess $access)
 {
     if (FieldAccess::WRITE !== $access->getAccessType()) {
         return $access->proceed();
     }
     foreach ($this->propertyWriteCheckers as $checker) {
         $checker($access);
     }
     return $access->proceed();
 }
Пример #6
0
 public function testWillNotProceedExecuteOnWriteAndCrash()
 {
     $this->fieldAccess->expects($this->never())->method('proceed')->will($this->returnValue('done'));
     $this->fieldAccess->expects($this->once())->method('getAccessType')->will($this->returnValue(FieldAccess::WRITE));
     foreach ($this->callables as $callable) {
         $callable->expects($this->any())->method('__invoke')->will($this->throwException(new \Exception()));
     }
     $aspect = new PropertyWriteAspect(...$this->callables);
     $this->setExpectedException(\Exception::class);
     $aspect->beforePropertyAccess($this->fieldAccess);
 }
 public function testWillFailOnInvalidAssignedType()
 {
     $field = new ReflectionProperty(ClassWithGenericArrayTypedProperty::class, 'property');
     $this->fieldAccess->expects($this->any())->method('getAccessType')->will($this->returnValue(FieldAccess::WRITE));
     $this->fieldAccess->expects($this->any())->method('getField')->will($this->returnValue($field));
     $this->fieldAccess->expects($this->any())->method('getValueToSet')->will($this->returnValue('new value'));
     $immutablePropertyCheck = new PropertyWriteTypeChecker();
     // catching the exception raised by PHPUnit by converting a fatal into an exception (in the error handler)
     $this->setExpectedException(\PHPUnit_Framework_Error::class);
     $immutablePropertyCheck->__invoke($this->fieldAccess);
 }
Пример #8
0
 /**
  * Advice that controls an access to the properties
  *
  * @param FieldAccess $fieldAccess Joinpoint
  *
  * @Around("access(public|protected Demo\Example\PropertyDemo->*)")
  * @return mixed
  */
 public function aroundFieldAccess(FieldAccess $fieldAccess)
 {
     $isRead = $fieldAccess->getAccessType() == FieldAccess::READ;
     // proceed all internal advices
     $fieldAccess->proceed();
     if ($isRead) {
         // if you want to change original property value, then return it by reference
         $value = $fieldAccess->getValue();
     } else {
         // if you want to change value to set, then return it by reference
         $value = $fieldAccess->getValueToSet();
     }
     echo "Calling After Interceptor for ", $fieldAccess, ", value: ", json_encode($value), PHP_EOL;
 }
Пример #9
0
 /**
  * Intercepts access to autowired properties and injects specified dependency
  *
  * @Around("@access(Warlock\Annotation\Autowired)")
  *
  * @param FieldAccess $joinpoint Autowiring joinpoint
  *
  * @return mixed
  */
 public function beforeAccessingAutowiredProperty(FieldAccess $joinpoint)
 {
     $obj = $joinpoint->getThis();
     $field = $joinpoint->getField();
     if ($joinpoint->getAccessType() == FieldAccess::READ) {
         /** @var Autowired $autowired */
         $autowired = $this->reader->getPropertyAnnotation($field, self::ANNOTATION_NAME);
         $strategy = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
         if (!$autowired->required) {
             $strategy = ContainerInterface::NULL_ON_INVALID_REFERENCE;
         }
         $value = $this->container->get($autowired, $strategy);
     } else {
         $value = $joinpoint->proceed();
     }
     $field->setValue($obj, $value);
     return $value;
 }
 /**
  * @param FieldAccess $access
  *
  * @return void
  *
  * @throws \RuntimeException
  */
 public function __invoke(FieldAccess $access)
 {
     if (!($that = $access->getThis())) {
         return;
     }
     if (FieldAccess::WRITE !== $access->getAccessType()) {
         return;
     }
     $field = $access->getField();
     $field->setAccessible(true);
     // simplistic check - won't check for multiple assignments of "null" to a "null" valued field
     if (null === ($currentValue = $field->getValue($that))) {
         return;
     }
     if (!(new DocBlock($field))->getTagsByName('immutable')) {
         return;
     }
     $newValue = $access->getValueToSet();
     throw new \RuntimeException(sprintf('Trying to overwrite property %s#$%s of object %s#%s with a value of type "%s".' . ' The property was already given a value of type %s', $field->getDeclaringClass()->getName(), $field->getName(), get_class($that), spl_object_hash($that), is_object($newValue) ? get_class($newValue) : gettype($newValue), is_object($currentValue) ? get_class($currentValue) : gettype($currentValue)));
 }
 public function testRaisesExceptionWhenFieldAccessIsInvalid()
 {
     $object = new ClassWithImmutableProperty();
     $field = new ReflectionProperty(ClassWithImmutableProperty::class, 'property');
     $object->property = 'initialized';
     $this->fieldAccess->expects($this->any())->method('getThis')->will($this->returnValue($object));
     $this->fieldAccess->expects($this->any())->method('getAccessType')->will($this->returnValue(FieldAccess::WRITE));
     $this->fieldAccess->expects($this->any())->method('getField')->will($this->returnValue($field));
     $immutablePropertyCheck = new PropertyWriteImmutabilityChecker();
     $this->setExpectedException(\RuntimeException::class);
     $immutablePropertyCheck->__invoke($this->fieldAccess);
 }
Пример #12
0
 /**
  * @param FieldAccess $access
  *
  * @return void
  *
  * @throws \ErrorException|\Exception
  */
 public function __invoke(FieldAccess $access)
 {
     if (FieldAccess::WRITE !== $access->getAccessType()) {
         return;
     }
     $that = $access->getThis();
     $contextClass = $that ? get_class($that) : $access->getField()->getDeclaringClass()->getName();
     $baseCheckers = [new IntegerTypeChecker(), new CallableTypeChecker(), new StringTypeChecker(), new GenericObjectTypeChecker(), new ObjectTypeChecker(), new ResourceTypeChecker(), new MixedTypeChecker(), new NullTypeChecker()];
     (new ApplyTypeChecks(new TypedTraversableChecker(...$baseCheckers), ...$baseCheckers))->__invoke((new PropertyTypeFinder())->__invoke($access->getField(), $contextClass), $access->getValueToSet());
 }