Completed
Push — master ( be02a5...a1ec95 )
by Nick
22:04 queued 02:39
created

EloquentJsQueries::serializeDate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace EloquentJs\Model;
4
5
use Carbon\Carbon;
6
use DateTime;
7
use EloquentJs\Query\Events\EloquentJsWasCalled;
8
use Illuminate\Database\Eloquent\Builder;
9
use InvalidArgumentException;
10
use UnexpectedValueException;
11
12
trait EloquentJsQueries
13
{
14
    /**
15
     * Scope to results that satisfy an EloquentJs query.
16
     *
17
     * @param Builder $query
18
     * @param string|null|callable $rules
19
     */
20
    public function scopeEloquentJs(Builder $query, $rules = null)
21
    {
22
        if ( ! static::$dispatcher) {
23
            throw new UnexpectedValueException(
24
                'Event dispatcher not found. Install illuminate/events package for EloquentJS usage without Laravel.'
25
            );
26
        }
27
28
        static::$dispatcher->fire(new EloquentJsWasCalled($query, $rules));
29
    }
30
31
    /**
32
     * Handle dynamic calls to scope methods.
33
     *
34
     * @param \Illuminate\Database\Eloquent\Builder $query
35
     * @param string $name
36
     * @param array $parameters
37
     */
38
    public function scopeScope($query, $name, $parameters = [])
39
    {
40
        $methodName = 'scope'.ucfirst($name);
41
42
        if ( ! method_exists($this, $methodName)) {
43
            throw new InvalidArgumentException("No such scope [$name]");
44
        }
45
46
        array_unshift($parameters, $query); // prepend $query to $parameters array
47
        call_user_func_array([$this, $methodName], $parameters);
48
    }
49
50
    /**
51
     * Prepare a date for array / JSON serialization.
52
     *
53
     * Overrides the date serializer to ensure our Javascript can
54
     * understand the format.
55
     *
56
     * @todo  implement date handling without global side effects
57
     * @param DateTime $date
58
     * @return string
59
     */
60
    protected function serializeDate(DateTime $date)
61
    {
62
        return $date->toIso8601String();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class DateTime as the method toIso8601String() does only exist in the following sub-classes of DateTime: Carbon\Carbon. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
63
    }
64
65
    /**
66
     * Return a timestamp as DateTime object.
67
     *
68
     * Accept dates from Javascript in any format that Carbon recognises.
69
     *
70
     * @param  string $value
71
     * @return Carbon
72
     */
73
    protected function asDateTime($value)
74
    {
75
        if (is_string($value)) {
76
            return Carbon::parse($value);
77
        }
78
79
        return parent::asDateTime($value);
80
    }
81
82
    /**
83
     * Get the endpoint defined on this model.
84
     *
85
     * @return string|null
86
     */
87
    public function getEndpoint()
88
    {
89
        if (property_exists($this, 'endpoint')) {
90
            return $this->endpoint;
91
        }
92
93
        return null;
94
    }
95
}
96