Completed
Pull Request — master (#20)
by
unknown
01:26
created

ProviderBase::shareCountRequestMultiple()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace SocialLinks\Providers;
4
5
use SocialLinks\Page;
6
use DOMDocument;
7
8
/**
9
 * Base class extended by all providers.
10
 *
11
 * @property string   $shareUrl
12
 * @property null|int $shareCount
13
 */
14
abstract class ProviderBase
15
{
16
    protected $page;
17
18
    const RFC1738 = 1;
19
    const RFC3986 = 2;
20
21
    /**
22
     * Constructor.
23
     *
24
     * @param Page $page
25
     */
26
    public function __construct(Page $page)
27
    {
28
        $this->page = $page;
29
    }
30
31
    /**
32
     * Magic method to calculate and store the properties.
33
     */
34
    public function __get($key)
35
    {
36
        switch ($key) {
37
            case 'shareUrl':
38
                return $this->shareUrl = $this->shareUrl();
39
40
            case 'shareCount':
41
42
                // Check cache, if option is set.
43
                if ($this->page->getConfig('useCache')) {
44
                    $id = $this->page->getId(get_class($this));
45
                    $now = time();
46
                    if ($cachedData = $this->page->cache->fetch($id)) {
0 ignored issues
show
Documentation introduced by
The property $cache is declared private in SocialLinks\Page. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
47
                        $expired = empty($cachedData[1]) || (
48
                            $cachedData[1] + $this->page->getConfig('cacheDuration') < $now
49
                        );
50
51
                        // If not expired, set shareCount and return.
52
                        if (!$expired) {
53
                            $this->shareCount = $cachedData[0];
54
                            return $this->shareCount;
55
                        }
56
                        // Else, remove from cache and continue.
57
                        else {
58
                            $this->page->cache->delete($id);
0 ignored issues
show
Documentation introduced by
The property $cache is declared private in SocialLinks\Page. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
59
                        }
60
                    }
61
                }
62
63
                if ($this->page->isMultiple()) {
64
                    $request = $this->shareCountRequestMultiple();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $request is correct as $this->shareCountRequestMultiple() (which targets SocialLinks\Providers\Pr...eCountRequestMultiple()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
65
                }
66
                else {
67
                    $request = $this->shareCountRequest();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $request is correct as $this->shareCountRequest() (which targets SocialLinks\Providers\Pr...se::shareCountRequest()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
68
                }
69
70
                if ($request !== null) {
71
                    $response = curl_exec($request) ?: '';
72
                    curl_close($request);
73
74
                    if ($this->page->isMultiple()) {
75
                        $this->shareCount = $this->shareCountMultiple($response);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $this->shareCount is correct as $this->shareCountMultiple($response) (which targets SocialLinks\Providers\Pr...e::shareCountMultiple()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
76
                    }
77
                    else {
78
                        $this->shareCount = $this->shareCount($response);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $this->shareCount is correct as $this->shareCount($response) (which targets SocialLinks\Providers\ProviderBase::shareCount()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
79
                    }
80
81
                    // Save in cache, if option is set.
82
                    if ($this->page->getConfig('useCache')) {
83
                        $this->page->cache->save($id, array($this->shareCount, $now));
0 ignored issues
show
Documentation introduced by
The property $cache is declared private in SocialLinks\Page. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Bug introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $now does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
84
                    }
85
86
                    return $this->shareCount;
87
                }
88
89
                return $this->shareCount = null;
90
        }
91
    }
92
93
    /**
94
     * Default shareCount function for providers without count api.
95
     *
96
     * {@inheritdoc}
97
     */
98
    public function shareCount($response)
99
    {
100
        return;
101
    }
102
103
    /**
104
     * Default shareCountRequest function for providers without count api.
105
     *
106
     * {@inheritdoc}
107
     */
108
    public function shareCountRequest()
109
    {
110
        return;
111
    }
112
113
    /**
114
     * Default shareCountMultiple function for providers without count api.
115
     *
116
     * {@inheritdoc}
117
     */
118
    public function shareCountMultiple($response)
119
    {
120
        return;
121
    }
122
123
    /**
124
     * Default shareCountRequestMultiple function for providers without
125
     * count api.
126
     *
127
     * {@inheritdoc}
128
     */
129
    public function shareCountRequestMultiple()
130
    {
131
        return;
132
    }
133
134
    /**
135
     * Generates a valid url.
136
     *
137
     * @param string $url
138
     * @param array  $pageParams parameters to be taken from page fields as $paramName  => $paramNameInTheURL
139
     * @param array  $getParams  extra parameters as $key => $value
140
     * @param int    $encoding   Type of encoding used. It can be static::RFC3986 or static::RFC1738
141
     *
142
     * @return string
143
     */
144
    protected function buildUrl($url, array $pageParams = null, array $getParams = array(), $encoding = self::RFC1738)
145
    {
146
        if ($pageParams) {
147
            $getParams += $this->page->get($pageParams);
148
        }
149
150
        if (empty($getParams)) {
151
            return $url;
152
        }
153
154
        if ($encoding === static::RFC1738) {
155
            return $url.'?'.http_build_query($getParams);
156
        }
157
158
        $get = array();
159
160
        foreach ($getParams as $name => $value) {
161
            $get[] = $name.'='.rawurlencode($value);
162
        }
163
164
        return $url.'?'.implode(ini_get('arg_separator.output'), $get);
165
    }
166
167
    /**
168
     * Build a curl request.
169
     *
170
     * @param string      $url
171
     * @param bool|string $post
172
     * @param array       $headers
173
     *
174
     * @return resource
175
     */
176
    protected static function request($url, $post = false, array $headers = null)
177
    {
178
        $connection = curl_init();
179
180
        curl_setopt_array($connection, array(
181
            CURLOPT_URL => $url,
182
            CURLOPT_RETURNTRANSFER => true,
183
            CURLOPT_FOLLOWLOCATION => true,
184
            CURLOPT_MAXREDIRS => 20,
185
            CURLOPT_CONNECTTIMEOUT => 10,
186
            CURLOPT_TIMEOUT => 10,
187
            CURLOPT_SSL_VERIFYPEER => false,
188
            CURLOPT_SSL_VERIFYHOST => false,
189
            CURLOPT_ENCODING => '',
190
            CURLOPT_AUTOREFERER => true,
191
            CURLOPT_USERAGENT => 'SocialLinks PHP Library',
192
        ));
193
194
        if (!empty($post)) {
195
            curl_setopt($connection, CURLOPT_POST, true);
196
197
            if (is_string($post)) {
198
                curl_setopt($connection, CURLOPT_POSTFIELDS, $post);
199
            }
200
        }
201
202
        if (!empty($headers)) {
203
            curl_setopt($connection, CURLOPT_HTTPHEADER, $headers);
204
        }
205
206
        return $connection;
207
    }
208
209
    /**
210
     * Handle JSON responses.
211
     *
212
     * @param string $content
213
     *
214
     * @return array|false
215
     */
216
    protected static function jsonResponse($content)
217
    {
218
        return json_decode($content, true);
219
    }
220
221
    /**
222
     * Handle JSONP responses.
223
     *
224
     * @param string $content
225
     *
226
     * @return array|false
227
     */
228
    protected static function jsonpResponse($content)
229
    {
230
        preg_match("/^\w+\((.*)\)$/", $content, $matches);
231
232
        return json_decode($matches[1], true);
233
    }
234
235
    /**
236
     * Handle HTML responses.
237
     *
238
     * @param string $content
239
     *
240
     * @return DOMDocument
241
     */
242
    protected static function htmlResponse($content)
243
    {
244
        $errors = libxml_use_internal_errors(true);
245
        $document = new DOMDocument();
246
        $document->loadHTML($content);
247
        libxml_use_internal_errors($errors);
248
249
        return $document;
250
    }
251
}
252