Completed
Push — tonesque/file_get_contents ( 794667...db7d56 )
by George
23:53 queued 14:27
created

Tonesque::grab_points()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 39
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 27
nc 3
nop 1
dl 0
loc 39
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/*
3
Plugin Name: Tonesque
4
Plugin URI: http://automattic.com/
5
Description: Grab an average color representation from an image.
6
Version: 1.0
7
Author: Automattic, Matias Ventura
8
Author URI: http://automattic.com/
9
License: GNU General Public License v2 or later
10
License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
*/
12
13
class Tonesque {
14
15
	private $image_url = '';
16
	private $image_obj = NULL;
17
	private $color = '';
18
19
	function __construct( $image_url ) {
20
		if ( ! class_exists( 'Jetpack_Color' ) ) {
21
			jetpack_require_lib( 'class.color' );
22
		}
23
24
		$this->image_url = esc_url_raw( $image_url );
25
		$this->image_url = trim( $this->image_url );
26
		/**
27
		 * Allows any image URL to be passed in for $this->image_url.
28
		 *
29
		 * @module theme-tools
30
		 *
31
		 * @since 2.5.0
32
		 *
33
		 * @param string $image_url The URL to any image
34
		 */
35
		$this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
36
37
		$this->image_obj = self::imagecreatefromurl( $this->image_url );
38
	}
39
40
	public static function imagecreatefromurl( $image_url ) {
41
		$data = null;
42
43
		// If it's a URL:
44
		if ( preg_match( '#^https?://#i', $image_url ) ) {
45
			// If it's a url pointing to a local media library url:
46
			$content_url = content_url();
47
			$_image_url  = set_url_scheme( $image_url );
48
			if ( wp_startswith( $_image_url, $content_url ) ) {
49
				$_image_path = str_replace( $content_url, ABSPATH . 'wp-content', $_image_url );
50 View Code Duplication
				if ( file_exists( $_image_path ) ) {
51
					list( $ext, $type ) = wp_check_filetype( $_image_path );
0 ignored issues
show
Unused Code introduced by
The assignment to $ext is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
52
					if ( wp_startswith( $type, 'image/' ) ) {
53
						$data = file_get_contents( $_image_path );
54
					}
55
				}
56
			}
57
58
			if ( empty( $data ) ) {
59
				$response = wp_remote_get( $image_url );
60
				if ( is_wp_error( $response ) ) {
61
					return $response;
62
				}
63
				$data = wp_remote_retrieve_body( $response );
64
			}
65
		}
66
67
		// If it's a local path in our WordPress install (no snooping around the filesystem):
68 View Code Duplication
		if ( file_exists( $image_url ) ) {
69
			list( $ext, $type ) = wp_check_filetype( $image_url );
0 ignored issues
show
Unused Code introduced by
The assignment to $ext is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
70
			if ( wp_startswith( $type, 'image/' ) ) {
71
				$data = file_get_contents( $image_url );
72
			}
73
		}
74
75
		// Now turn it into an image and return it.
76
		return imagecreatefromstring( $data );
77
	}
78
79
	/**
80
	 *
81
	 * Construct object from image.
82
	 *
83
	 * @param optional $type (hex, rgb, hsl)
0 ignored issues
show
Documentation introduced by
Should the type for parameter $type not be string|optional?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
84
	 * @return color as a string formatted as $type
85
	 *
86
 	 */
87
	function color( $type = 'hex' ) {
88
		// Bail if there is no image to work with
89
	 	if ( ! $this->image_obj )
90
			return false;
91
92
		// Finds dominant color
93
		$color = self::grab_color();
94
		// Passes value to Color class
95
		$color = self::get_color( $color, $type );
96
		return $color;
97
	}
98
99
	/**
100
	 *
101
	 * Grabs the color index for each of five sample points of the image
102
	 *
103
	 * @param $image
104
	 * @param $type can be 'index' or 'hex'
105
	 * @return array() with color indices
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
106
	 *
107
 	 */
108
	function grab_points( $type = 'index' ) {
109
		$img = $this->image_obj;
110
		if ( ! $img )
111
			return false;
112
113
		$height = imagesy( $img );
114
		$width  = imagesx( $img );
115
116
		// Sample five points in the image
117
		// Based on rule of thirds and center
118
		$topy    = round( $height / 3 );
119
		$bottomy = round( ( $height / 3 ) * 2 );
120
		$leftx   = round( $width / 3 );
121
		$rightx  = round( ( $width / 3 ) * 2 );
122
		$centery = round( $height / 2 );
123
		$centerx = round( $width / 2 );
124
125
		// Cast those colors into an array
126
		$points = array(
127
			imagecolorat( $img, $leftx, $topy ),
128
			imagecolorat( $img, $rightx, $topy ),
129
			imagecolorat( $img, $leftx, $bottomy ),
130
			imagecolorat( $img, $rightx, $bottomy ),
131
			imagecolorat( $img, $centerx, $centery ),
132
		);
133
134
		if ( 'hex' == $type ) {
135
			foreach ( $points as $i => $p ) {
136
				$c = imagecolorsforindex( $img, $p );
137
				$points[ $i ] = self::get_color( array(
138
					'r' => $c['red'],
139
					'g' => $c['green'],
140
					'b' => $c['blue'],
141
				), 'hex' );
142
			}
143
		}
144
145
		return $points;
146
	}
147
148
	/**
149
	 *
150
	 * Finds the average color of the image based on five sample points
151
	 *
152
	 * @param $image
153
	 * @return array() with rgb color
0 ignored issues
show
Documentation introduced by
The doc-type array() could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
154
	 *
155
 	 */
156
	function grab_color() {
157
		$img = $this->image_obj;
158
		if ( ! $img )
159
			return false;
160
161
		$rgb = self::grab_points();
162
163
		// Process the color points
164
		// Find the average representation
165
		foreach ( $rgb as $color ) {
0 ignored issues
show
Bug introduced by
The expression $rgb of type false|array<integer,integer|string> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
166
			$index = imagecolorsforindex( $img, $color );
167
			$r[] = $index['red'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$r was never initialized. Although not strictly required by PHP, it is generally a good practice to add $r = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
168
			$g[] = $index['green'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$g was never initialized. Although not strictly required by PHP, it is generally a good practice to add $g = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
169
			$b[] = $index['blue'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$b was never initialized. Although not strictly required by PHP, it is generally a good practice to add $b = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
170
171
			$red = round( array_sum( $r ) / 5 );
0 ignored issues
show
Bug introduced by
The variable $r 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...
172
			$green = round( array_sum( $g ) / 5 );
0 ignored issues
show
Bug introduced by
The variable $g 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...
173
			$blue = round( array_sum( $b ) / 5 );
0 ignored issues
show
Bug introduced by
The variable $b 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...
174
		}
175
176
		// The average color of the image as rgb array
177
		$color = array(
178
			'r' => $red,
0 ignored issues
show
Bug introduced by
The variable $red 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...
179
			'g' => $green,
0 ignored issues
show
Bug introduced by
The variable $green 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...
180
			'b' => $blue,
0 ignored issues
show
Bug introduced by
The variable $blue 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...
181
		);
182
183
		return $color;
184
	}
185
186
	/**
187
	 *
188
	 * Get a Color object using /lib class.color
189
	 * Convert to appropriate type
190
	 *
191
	 * @return string
192
	 *
193
	 */
194
	function get_color( $color, $type ) {
195
		$c = new Jetpack_Color( $color, 'rgb' );
196
		$this->color = $c;
0 ignored issues
show
Documentation Bug introduced by
It seems like $c of type object<Jetpack_Color> is incompatible with the declared type string of property $color.

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...
197
198
		switch ( $type ) {
199
			case 'rgb' :
200
				$color = implode( $c->toRgbInt(), ',' );
201
				break;
202
			case 'hex' :
203
				$color = $c->toHex();
204
				break;
205
			case 'hsv' :
206
				$color = implode( $c->toHsvInt(), ',' );
207
				break;
208
			default:
209
				return $color = $c->toHex();
0 ignored issues
show
Unused Code introduced by
$color is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
210
		}
211
212
		return $color;
213
	}
214
215
	/**
216
	 *
217
	 * Checks contrast against main color
218
	 * Gives either black or white for using with opacity
219
	 *
220
	 * @return string
221
	 *
222
 	 */
223
	function contrast() {
224
	 	if ( ! $this->color )
225
			return false;
226
227
		$c = $this->color->getMaxContrastColor();
0 ignored issues
show
Bug introduced by
The method getMaxContrastColor cannot be called on $this->color (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
228
		return implode( $c->toRgbInt(), ',' );
229
	}
230
231
};
232