Completed
Push — master ( 2723b8...b8ac50 )
by Jelle
03:22
created

Proxy::get()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 17
rs 9.2
cc 4
eloc 7
nc 4
nop 1
1
<?php
2
/**
3
 * @file
4
 * Contains \TheSportsDb\Entity\Proxy\Proxy.
5
 */
6
7
namespace TheSportsDb\Entity\Proxy;
8
9
use TheSportsDb\Http\TheSportsDbClientInterface;
10
use TheSportsDb\Entity\EntityManagerInterface;
11
use TheSportsDb\Entity\EntityInterface;
12
use TheSportsDb\Entity\EntityManagerConsumerTrait;
13
14
/**
15
 * Default implementation of proxy objects.
16
 *
17
 * @author Jelle Sebreghts
18
 */
19
abstract class Proxy implements ProxyInterface {
1 ignored issue
show
Coding Style introduced by
Proxy does not seem to conform to the naming convention (^Abstract|Factory$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
20
  use EntityManagerConsumerTrait;
21
  /**
22
   * The sports db client.
23
   *
24
   * @var TheSportsDb\Http\TheSportsDbClientInterface
25
   */
26
  protected $sportsDbClient;
27
28
  /**
29
   * The already available properties.
30
   *
31
   * @var \stdClass
32
   */
33
  protected $properties;
34
35
  /**
36
   * The fully loaded entity object (lazy-loaded when needed).
37
   *
38
   * @var mixed
39
   */
40
  protected $entity;
41
42
  /**
43
   * Creates a new Proxy object.
44
   *
45
   * @param \stdClass $values
46
   *   The sport data.
47
   * @param \TheSportsDb\Http\TheSportsDbClientInterface $sportsDbClient
0 ignored issues
show
Bug introduced by
There is no parameter named $sportsDbClient. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
48
   *   A sports db client
49
   * @param \TheSportsDb\Entity\Factory\FactoryInterface $factory
0 ignored issues
show
Bug introduced by
There is no parameter named $factory. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
50
   *   The sport factory.
51
   */
52
  public function __construct(\stdClass $values) {
53
    $this->properties = new \stdClass();
54
    $this->update($values);
55
  }
56
57
  public function update(\stdClass $values) {
58
    foreach ((array) $values as $prop => $val) {
59
      if (method_exists($this, 'get' . ucfirst($prop))) {
60
        $this->properties->{$prop} = $val;
61
      }
62
    }
63
    if ($this->entityManager && $this->entityManager->factory($this->getEntityType())->isFullObject($this->properties, $this->getEntityType())) {
64
      $this->entity = $this->entityManager->factory($this->getEntityType())->create($this->properties, $this->getEntityType(), FALSE);
65
    }
66
  }
67
68
  public function setEntityManager(EntityManagerInterface $entityManager) {
69
    $this->entityManager = $entityManager;
0 ignored issues
show
Documentation Bug introduced by
It seems like $entityManager of type object<TheSportsDb\Entity\EntityManagerInterface> is incompatible with the declared type object<TheSportsDb\Entit...EntityManagerInterface> of property $entityManager.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
70
    // Check if we can create a full object once the entity manager is set.
71
    $stub = new \stdClass();
72
    $this->update($stub);
73
  }
74
75
  public function setSportsDbClient(TheSportsDbClientInterface $sportsDbClient) {
76
    $this->sportsDbClient = $sportsDbClient;
0 ignored issues
show
Documentation Bug introduced by
It seems like $sportsDbClient of type object<TheSportsDb\Http\...portsDbClientInterface> is incompatible with the declared type object<TheSportsDb\Entit...portsDbClientInterface> of property $sportsDbClient.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
77
  }
78
79
  /**
80
   * Gets a property, if it exists, loads it if necessary.
81
   *
82
   * @param string $name
83
   *   The property name.
84
   *
85
   * @return mixed
86
   *   The property value.
87
   */
88
  protected function get($name) {
89
    // If the full entity is loaded, use it.
90
    if ($this->entity instanceof EntityInterface) {
91
      return $this->entity->{'get' . ucfirst($name)}();
92
    }
93
94
        // If the property exists on the proxy, use it.
95
    if (isset($this->properties->{$name})) {
96
      return $this->properties->{$name};
97
    }
98
99
    // The property does not exist on the proxy, and the entity is not loaded in
100
    // full yet, so load it first and repeat the operation.
101
    method_exists($this, 'load' . ucfirst($name)) ? $this->{'load' . ucfirst($name)}() : $this->load();
102
    return $this->get($name);
103
    
104
  }
105
106
  /**
107
   * Lazy loads an entity.
108
   *
109
   * @throws \Exception
110
   *   When the entity is not found.
111
   */
112
  abstract protected function load();
0 ignored issues
show
Documentation introduced by
For interfaces and abstract methods it is generally a good practice to add a @return annotation even if it is just @return void or @return null, so that implementors know what to do in the overridden method.

For interface and abstract methods, it is impossible to infer the return type from the immediate code. In these cases, it is generally advisible to explicitly annotate these methods with a @return doc comment to communicate to implementors of these methods what they are expected to return.

Loading history...
113
114
  public function raw() {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
115
    if ($this->entity) {
116
      $this->_raw = $this->entity->raw();
1 ignored issue
show
Bug introduced by
The property _raw does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
117
      return $this->_raw;
118
    }
119
    if (!isset($this->_raw)) {
120
      $this->_raw = new \stdClass();
121
    }
122
    $reflection = new \ReflectionClass($this);
123
    $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
1 ignored issue
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
124
    foreach ($methods as $method) {
125
      $methodName = $method->getName();
126
      if (strpos($methodName, 'get') === 0) {
127
        $prop = lcfirst(substr($methodName, 3));
128
        if (isset($this->properties->{$prop}) && !property_exists($this->_raw, $prop)) {
129
          $this->_raw->{$prop} = NULL;
130
          $val = $this->{$methodName}();
1 ignored issue
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 17 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
131
          $this->_raw->{$prop} = $val;
132 View Code Duplication
          if (method_exists($val, 'raw')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
            $this->_raw->{$prop} = $val->raw();
134
          }
135
          elseif (is_array($val)) {
136
            $this->_raw->{$prop} = array();
137
            foreach ($val as $v) {
138
              $this->_raw->{$prop}[] = method_exists($v, 'raw') ? $v->raw() : $v;
139
            }
140
          }
141
        }
142
      }
143
    }
144
    return $this->_raw;
145
  }
146
147
  public static function getEntityType() {
148
    $reflection = new \ReflectionClass(static::class);
149
    return strtolower(substr($reflection->getShortName(), 0, -5));
150
  }
151
152
  public static function getPropertyMapDefinition() {
153
    $reflection = new \ReflectionClass(substr(static::class, 0, -5));
154
    return $reflection->getStaticPropertyValue('propertyMapDefinition');
155
  }
156
}
157