Completed
Push — sync/json-endpoints-19apr2017 ( 4d1744 )
by
unknown
64:46 queued 53:25
created

_inc/lib/tonesque.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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, WP_CONTENT_DIR, $_image_url );
50 View Code Duplication
				if ( file_exists( $_image_path ) ) {
51
					$filetype = wp_check_filetype( $_image_path );
52
					$ext = $filetype['ext'];
53
					$type = $filetype['type'];
54
55
					if ( wp_startswith( $type, 'image/' ) ) {
56
						$data = file_get_contents( $_image_path );
57
					}
58
				}
59
			}
60
61
			if ( empty( $data ) ) {
62
				$response = wp_remote_get( $image_url );
63
				if ( is_wp_error( $response ) ) {
64
					return false;
65
				}
66
				$data = wp_remote_retrieve_body( $response );
67
			}
68
		}
69
70
		// If it's a local path in our WordPress install:
71 View Code Duplication
		if ( file_exists( $image_url ) ) {
72
			$filetype = wp_check_filetype( $image_url );
73
			$ext = $filetype['ext'];
74
			$type = $filetype['type'];
75
76
			if ( wp_startswith( $type, 'image/' ) ) {
77
				$data = file_get_contents( $image_url );
78
			}
79
		}
80
81
		// Now turn it into an image and return it.
82
		return imagecreatefromstring( $data );
83
	}
84
85
	/**
86
	 *
87
	 * Construct object from image.
88
	 *
89
	 * @param optional $type (hex, rgb, hsl)
90
	 * @return color as a string formatted as $type
91
	 *
92
 	 */
93
	function color( $type = 'hex' ) {
94
		// Bail if there is no image to work with
95
	 	if ( ! $this->image_obj )
96
			return false;
97
98
		// Finds dominant color
99
		$color = self::grab_color();
100
		// Passes value to Color class
101
		$color = self::get_color( $color, $type );
102
		return $color;
103
	}
104
105
	/**
106
	 *
107
	 * Grabs the color index for each of five sample points of the image
108
	 *
109
	 * @param $image
110
	 * @param $type can be 'index' or 'hex'
111
	 * @return array() with color indices
112
	 *
113
 	 */
114
	function grab_points( $type = 'index' ) {
115
		$img = $this->image_obj;
116
		if ( ! $img )
117
			return false;
118
119
		$height = imagesy( $img );
120
		$width  = imagesx( $img );
121
122
		// Sample five points in the image
123
		// Based on rule of thirds and center
124
		$topy    = round( $height / 3 );
125
		$bottomy = round( ( $height / 3 ) * 2 );
126
		$leftx   = round( $width / 3 );
127
		$rightx  = round( ( $width / 3 ) * 2 );
128
		$centery = round( $height / 2 );
129
		$centerx = round( $width / 2 );
130
131
		// Cast those colors into an array
132
		$points = array(
133
			imagecolorat( $img, $leftx, $topy ),
134
			imagecolorat( $img, $rightx, $topy ),
135
			imagecolorat( $img, $leftx, $bottomy ),
136
			imagecolorat( $img, $rightx, $bottomy ),
137
			imagecolorat( $img, $centerx, $centery ),
138
		);
139
140
		if ( 'hex' == $type ) {
141
			foreach ( $points as $i => $p ) {
142
				$c = imagecolorsforindex( $img, $p );
143
				$points[ $i ] = self::get_color( array(
144
					'r' => $c['red'],
145
					'g' => $c['green'],
146
					'b' => $c['blue'],
147
				), 'hex' );
148
			}
149
		}
150
151
		return $points;
152
	}
153
154
	/**
155
	 *
156
	 * Finds the average color of the image based on five sample points
157
	 *
158
	 * @param $image
159
	 * @return array() with rgb color
160
	 *
161
 	 */
162
	function grab_color() {
163
		$img = $this->image_obj;
164
		if ( ! $img )
165
			return false;
166
167
		$rgb = self::grab_points();
168
169
		// Process the color points
170
		// Find the average representation
171
		foreach ( $rgb as $color ) {
172
			$index = imagecolorsforindex( $img, $color );
173
			$r[] = $index['red'];
174
			$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...
175
			$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...
176
177
			$red = round( array_sum( $r ) / 5 );
0 ignored issues
show
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...
178
			$green = round( array_sum( $g ) / 5 );
0 ignored issues
show
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...
179
			$blue = round( array_sum( $b ) / 5 );
0 ignored issues
show
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...
180
		}
181
182
		// The average color of the image as rgb array
183
		$color = array(
184
			'r' => $red,
185
			'g' => $green,
186
			'b' => $blue,
187
		);
188
189
		return $color;
190
	}
191
192
	/**
193
	 *
194
	 * Get a Color object using /lib class.color
195
	 * Convert to appropriate type
196
	 *
197
	 * @return string
198
	 *
199
	 */
200
	function get_color( $color, $type ) {
201
		$c = new Jetpack_Color( $color, 'rgb' );
202
		$this->color = $c;
203
204
		switch ( $type ) {
205
			case 'rgb' :
206
				$color = implode( $c->toRgbInt(), ',' );
207
				break;
208
			case 'hex' :
209
				$color = $c->toHex();
210
				break;
211
			case 'hsv' :
212
				$color = implode( $c->toHsvInt(), ',' );
213
				break;
214
			default:
215
				return $color = $c->toHex();
216
		}
217
218
		return $color;
219
	}
220
221
	/**
222
	 *
223
	 * Checks contrast against main color
224
	 * Gives either black or white for using with opacity
225
	 *
226
	 * @return string
227
	 *
228
 	 */
229
	function contrast() {
230
	 	if ( ! $this->color )
231
			return false;
232
233
		$c = $this->color->getMaxContrastColor();
0 ignored issues
show
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...
234
		return implode( $c->toRgbInt(), ',' );
235
	}
236
237
};
238