Compress JPEG & PNG images - Version 1.3.0

Version Description

  • Improved bulk compressions from media library. You can now also bulk compress your whole media library in one step.
  • Intelligent detection if file is already compressed or was altered by another plugin and should be recompressed.
Download this release

Release Info

Developer TinyPNG
Plugin Icon 128x128 Compress JPEG & PNG images
Version 1.3.0
Comparing to
See all releases

Code changes from version 1.1.0 to 1.3.0

Files changed (66) hide show
  1. .travis.yml +9 -10
  2. README.md +4 -3
  3. RELEASE +7 -3
  4. bin/format-language-files +1 -1
  5. bin/integration-tests +51 -0
  6. bin/restore-wordpress +25 -0
  7. bin/test-wordpress +10 -3
  8. bin/unit-tests +3 -0
  9. composer.json +3 -1
  10. composer.lock +1058 -12
  11. config/Dockerfile-wordpress-30 +2 -1
  12. config/Dockerfile-wordpress-31 +2 -1
  13. config/Dockerfile-wordpress-32 +2 -1
  14. config/Dockerfile-wordpress-33 +2 -1
  15. config/Dockerfile-wordpress-34 +2 -1
  16. config/Dockerfile-wordpress-35 +2 -1
  17. config/Dockerfile-wordpress-36 +2 -1
  18. config/Dockerfile-wordpress-37 +5 -4
  19. config/Dockerfile-wordpress-38 +5 -4
  20. config/Dockerfile-wordpress-39 +5 -4
  21. config/Dockerfile-wordpress-40 +5 -4
  22. config/Dockerfile-wordpress-41 +10 -3
  23. config/Dockerfile-wordpress-42 +15 -0
  24. readme.txt +17 -3
  25. src/cacert.pem +307 -213
  26. src/class-tiny-compress-curl.php +13 -7
  27. src/class-tiny-compress-fopen.php +7 -3
  28. src/class-tiny-compress.php +32 -15
  29. src/class-tiny-metadata.php +60 -4
  30. src/class-tiny-notices.php +122 -0
  31. src/class-tiny-plugin.php +144 -69
  32. src/class-tiny-settings.php +106 -7
  33. src/class-tiny-wp-base.php +42 -8
  34. src/config/tiny-config.php +5 -0
  35. src/config/tinypng-api.ini +0 -2
  36. src/languages/tiny-compress-images-nl_NL.mo +0 -0
  37. src/languages/tiny-compress-images-nl_NL.po +92 -2
  38. src/languages/tiny-compress-images-ru_RU.mo +0 -0
  39. src/languages/tiny-compress-images-ru_RU.po +125 -0
  40. src/scripts/admin.js +148 -15
  41. src/styles/admin.css +51 -1
  42. test/fixtures/{example-tinypng.png → input-example.jpg} +0 -0
  43. test/fixtures/{example-tinyjpg.jpg → input-example.png} +0 -0
  44. test/fixtures/{example-large.png → input-large.png} +0 -0
  45. test/fixtures/tiny-config.php +5 -0
  46. test/fixtures/tinypng-api.ini +0 -2
  47. test/helpers/compress.php +0 -31
  48. test/helpers/setup.php +42 -20
  49. test/helpers/wordpress.php +55 -11
  50. test/integration/BulkCompressIntegrationTest.php +54 -14
  51. test/integration/CompressIntegrationTest.php +43 -7
  52. test/integration/IntegrationTestCase.php +9 -3
  53. test/integration/SettingsIntegrationTest.php +37 -0
  54. test/mock-tinypng-webservice/.htaccess +1 -0
  55. test/mock-tinypng-webservice/example-tinyjpg.jpg +0 -0
  56. test/mock-tinypng-webservice/example-tinypng.png +0 -0
  57. test/mock-tinypng-webservice/output-example.jpg +0 -0
  58. test/mock-tinypng-webservice/output-example.png +0 -0
  59. test/mock-tinypng-webservice/output-large.png +0 -0
  60. test/mock-tinypng-webservice/output.php +9 -15
  61. test/mock-tinypng-webservice/reset.php +7 -0
  62. test/mock-tinypng-webservice/shrink.php +95 -17
  63. test/unit/TinyPluginTest.php +91 -18
  64. test/unit/TinySettingsTest.php +3 -1
  65. test/unit/TinyTestCase.php +5 -3
  66. tiny-compress-images.php +7 -1
.travis.yml CHANGED
@@ -1,13 +1,12 @@
1
  language: php
2
-
3
  php:
4
- - 5.3
5
- - 5.4
6
- - 5.5
7
- - 5.6
8
- - hhvm
9
-
10
  before_script: composer install
11
-
12
- script: phpunit --process-isolation test/unit
13
-
 
1
  language: php
 
2
  php:
3
+ - 5.3
4
+ - 5.4
5
+ - 5.5
6
+ - 5.6
7
+ - hhvm
 
8
  before_script: composer install
9
+ script: bin/unit-tests
10
+ notifications:
11
+ slack:
12
+ secure: uttJ78cpkV9czhoKXtAoop8UBWPVtF+fwKlKS47c4EW7ZfVx9jAII2yLb5yZjdLDnM7YAluujUBIqyESvwLY0h7azLsorSIEqNt9GlBi4B7DSGAdo46lFbqsdjrLwM1gOhiP7Fl4hFiQ2+jA9Fsj3W2yZ6rbF7endv7Gx5FMlFg=
README.md CHANGED
@@ -15,7 +15,6 @@ Got questions or feedback? Let us know! Contact us at support@tinypng.com.
15
  ### Prerequisites
16
  * A working docker installation (https://docs.docker.com/installation/).
17
  * Composer (https://getcomposer.org/download/).
18
- * PHPUnit (https://phpunit.de/getting-started.html).
19
  * Selenium Server (http://www.seleniumhq.org/download/).
20
  * Mysql client and admin tools.
21
  * Java runtime.
@@ -25,11 +24,11 @@ Got questions or feedback? Let us know! Contact us at support@tinypng.com.
25
  2. Use `docker ps` to check which port to use to connect to WordPress.
26
 
27
  ### Running the unit tests
28
- 1. Run `phpunit --process-isolation test/unit`.
29
 
30
  ### Running the integration tests
31
  1. Start Selenium server: `java -jar selenium-server-standalone-2.44.0.jar`.
32
- 2. Run `bin/test-wordpress <version>`. E.g. `bin/test-wordpress 41`.
33
 
34
  Note that when testing a different WordPress version, `bin/run-wordpress <version>` has to be run first.
35
 
@@ -45,3 +44,5 @@ This program is distributed in the hope that it will be useful,
45
  but WITHOUT ANY WARRANTY; without even the implied warranty of
46
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47
  GNU General Public License for more details.
 
 
15
  ### Prerequisites
16
  * A working docker installation (https://docs.docker.com/installation/).
17
  * Composer (https://getcomposer.org/download/).
 
18
  * Selenium Server (http://www.seleniumhq.org/download/).
19
  * Mysql client and admin tools.
20
  * Java runtime.
24
  2. Use `docker ps` to check which port to use to connect to WordPress.
25
 
26
  ### Running the unit tests
27
+ 1. Run `bin/unit-tests`.
28
 
29
  ### Running the integration tests
30
  1. Start Selenium server: `java -jar selenium-server-standalone-2.44.0.jar`.
31
+ 2. Run `bin/integration-tests $version [$to_version]`. E.g. `bin/run-wordpress 41` or `bin/integration-tests 40 42`.
32
 
33
  Note that when testing a different WordPress version, `bin/run-wordpress <version>` has to be run first.
34
 
44
  but WITHOUT ANY WARRANTY; without even the implied warranty of
45
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46
  GNU General Public License for more details.
47
+
48
+ [View the complete license](LICENSE).
RELEASE CHANGED
@@ -6,6 +6,10 @@ In order to release a new version of the plugin to wordpress.org, perform the fo
6
  4. Create a new release in GitHub and pull it in.
7
  5. Locally, checkout the new tag: `git checkout <tagged version>`.
8
  6. If not already done so, checkout the plugin's Subversion repository: `svn co http://plugins.svn.wordpress.org/tiny-compress-images`.
9
- 7. Manually copy the Git release to the local Subversion repo: `cp -R . <path-to-local-svn-repo>/trunk/`.
10
- 8. Commit the trunk to Subversion: `svn add trunk/* && svn ci -m "<message>".
11
- 9. Tag the new release in Subversion and commit: `svn cp trunk tags/<version> && svn ci -m "<message>"`.
 
 
 
 
6
  4. Create a new release in GitHub and pull it in.
7
  5. Locally, checkout the new tag: `git checkout <tagged version>`.
8
  6. If not already done so, checkout the plugin's Subversion repository: `svn co http://plugins.svn.wordpress.org/tiny-compress-images`.
9
+ 7. Update svn:ignore property of trunk when .gitignore is updated: `svn propedit svn:ignore trunk`.
10
+ 8. Delete everything in trunk `rm -rf <path-to-local-svn-repo/trunk/*`.
11
+ 9. Manually copy the Git release to the local Subversion repo: `git ls-files | xargs tar c | tar x -C <path-to-local-svn-repo>/trunk/`.
12
+ 10. Add new files `svn st | awk '/^\?/ { print $2; }' | xargs svn add`.
13
+ 11. Delete deleted files: `svn st | awk '/^!/ { print $2; }' | xargs svn rm`.
14
+ 12. Commit the trunk to Subversion: `svn ci -m "<message>"`.
15
+ 13. Tag the new release in Subversion and commit: `svn cp trunk tags/<version> && svn ci -m "<message>"`.
bin/format-language-files CHANGED
@@ -2,7 +2,7 @@
2
 
3
  use strict;
4
  use warnings;
5
- use File::Basename;
6
 
7
  my $dir = dirname($0);
8
  open FIND, "find $dir/../src/languages -type f -name '*.po' |";
2
 
3
  use strict;
4
  use warnings;
5
+ use File::Basename qw(dirname fileparse);
6
 
7
  my $dir = dirname($0);
8
  open FIND, "find $dir/../src/languages -type f -name '*.po' |";
bin/integration-tests ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env perl
2
+
3
+ use strict;
4
+ use warnings;
5
+ use File::Basename qw(dirname);
6
+ use IO::Socket;
7
+ use Time::HiRes qw(usleep);
8
+
9
+ my $dir = dirname($0);
10
+ my $hostip = `boot2docker ip`;
11
+
12
+ sub check_port {
13
+ my ($ip, $port, $times, $sleep) = @_;
14
+ for (my $i = 0; $i < $times; $i++) {
15
+ my $sock = IO::Socket::INET->new(
16
+ PeerAddr => $ip,
17
+ PeerPort => $port,
18
+ Proto => 'tcp',
19
+ Timeout => 2
20
+ );
21
+ return 1 if $sock;
22
+ usleep($sleep * 1000);
23
+ }
24
+ return 0;
25
+ }
26
+
27
+ my $from = $ARGV[0] || 42;
28
+ my $to = $ARGV[1] || $from;
29
+
30
+ for (my $version = $from; $version <= $to; $version++) {
31
+ printf("==================== Wordpress %d ====================\n", $version);
32
+ print(" - Running\n");
33
+ my $ret = system("$dir/run-wordpress $version > /dev/null 2>&1");
34
+ if ($ret) {
35
+ print(" Error: $ret\n");
36
+ next;
37
+ }
38
+ print(" - Waiting\n");
39
+ sleep(10);
40
+ print(" - Checking\n");
41
+ if (!check_port($hostip, 8000 + $version, 10, 500)) {
42
+ print(" Error: No open port\n");
43
+ next;
44
+ }
45
+ print(" - Testing\n");
46
+ $ret = system("$dir/test-wordpress $version");
47
+ if ($ret) {
48
+ print(" Error: $ret\n");
49
+ next;
50
+ }
51
+ }
bin/restore-wordpress ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ display_usage() {
6
+ echo -e "Usage:\n\t$0 <version> \n\nExample:\n\t$0 41"
7
+ }
8
+
9
+ if [ $# -ne 1 ]
10
+ then
11
+ display_usage
12
+ exit 1
13
+ fi
14
+
15
+ version="$1"
16
+ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
17
+ source $DIR/docker-functions
18
+
19
+ export WORDPRESS_VERSION=$version
20
+ export WORDPRESS_DATABASE=wordpress_$version
21
+ export MYSQL_ROOT_PASSWORD=root
22
+ export HOST_IP=$(boot2docker ip)
23
+ export MYSQL_DUMP_FILE=tmp/mysqldump_wordpress_$version.sql.gz
24
+
25
+ gunzip -c < $MYSQL_DUMP_FILE | mysql -h $HOST_IP -u root "-p$MYSQL_ROOT_PASSWORD" $WORDPRESS_DATABASE
bin/test-wordpress CHANGED
@@ -3,10 +3,10 @@
3
  set -e
4
 
5
  display_usage() {
6
- echo -e "Usage:\n\t$0 <version> \n\nExample:\n\t$0 41"
7
  }
8
 
9
- if [ $# -ne 1 ]
10
  then
11
  display_usage
12
  exit 1
@@ -16,10 +16,17 @@ version="$1"
16
  DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
17
  source $DIR/docker-functions
18
 
 
 
 
 
 
 
 
19
  export WORDPRESS_VERSION=$version
20
  export WORDPRESS_DATABASE=wordpress_$version
21
  export MYSQL_ROOT_PASSWORD=root
22
  export HOST_IP=$(boot2docker ip)
23
  export HOST_PORT=80$version
24
  export WORDPRESS_URL=http://$(boot2docker ip):$HOST_PORT
25
- phpunit test/integration
3
  set -e
4
 
5
  display_usage() {
6
+ echo -e "Usage:\n\t$0 <version> [IntegrationTestFile.php] \n\nExample:\n\t$0 41"
7
  }
8
 
9
+ if [ $# -eq 0 ]
10
  then
11
  display_usage
12
  exit 1
16
  DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
17
  source $DIR/docker-functions
18
 
19
+ if [ $# -ge 2 ]
20
+ then
21
+ PHPUNIT_ARG="$2"
22
+ else
23
+ PHPUNIT_ARG="test/integration"
24
+ fi
25
+
26
  export WORDPRESS_VERSION=$version
27
  export WORDPRESS_DATABASE=wordpress_$version
28
  export MYSQL_ROOT_PASSWORD=root
29
  export HOST_IP=$(boot2docker ip)
30
  export HOST_PORT=80$version
31
  export WORDPRESS_URL=http://$(boot2docker ip):$HOST_PORT
32
+ vendor/bin/phpunit "$PHPUNIT_ARG"
bin/unit-tests ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ #!/bin/sh
2
+
3
+ vendor/bin/phpunit --process-isolation test/unit $@
composer.json CHANGED
@@ -3,6 +3,8 @@
3
  "facebook/webdriver": "0.5.*"
4
  },
5
  "require-dev": {
6
- "mockery/mockery": "dev-master"
 
 
7
  }
8
  }
3
  "facebook/webdriver": "0.5.*"
4
  },
5
  "require-dev": {
6
+ "phpunit/phpunit": "~4.6",
7
+ "mikey179/vfsStream": "~1.5",
8
+ "mockery/mockery": "~0.9"
9
  }
10
  }
composer.lock CHANGED
@@ -4,7 +4,7 @@
4
  "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
- "hash": "5af0566aedacef6cbdee2ce7dea70d1f",
8
  "packages": [
9
  {
10
  "name": "facebook/webdriver",
@@ -49,28 +49,172 @@
49
  }
50
  ],
51
  "packages-dev": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  {
53
  "name": "mockery/mockery",
54
- "version": "dev-master",
55
  "source": {
56
  "type": "git",
57
  "url": "https://github.com/padraic/mockery.git",
58
- "reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e"
59
  },
60
  "dist": {
61
  "type": "zip",
62
- "url": "https://api.github.com/repos/padraic/mockery/zipball/f770ab0cf167cccf1a701f28411fbfc9971ff90e",
63
- "reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e",
64
  "shasum": ""
65
  },
66
  "require": {
 
67
  "lib-pcre": ">=7.0",
68
  "php": ">=5.3.2"
69
  },
70
  "require-dev": {
71
- "hamcrest/hamcrest-php": "~1.1",
72
- "phpunit/phpunit": "~4.0",
73
- "satooshi/php-coveralls": "~0.7@dev"
74
  },
75
  "type": "library",
76
  "extra": {
@@ -113,15 +257,917 @@
113
  "test double",
114
  "testing"
115
  ],
116
- "time": "2015-02-11 12:43:02"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
118
  ],
119
  "aliases": [],
120
  "minimum-stability": "stable",
121
- "stability-flags": {
122
- "mockery/mockery": 20
123
- },
124
  "prefer-stable": false,
 
125
  "platform": [],
126
  "platform-dev": []
127
  }
4
  "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
  "This file is @generated automatically"
6
  ],
7
+ "hash": "14e67ae14aec130373c8ff715c963454",
8
  "packages": [
9
  {
10
  "name": "facebook/webdriver",
49
  }
50
  ],
51
  "packages-dev": [
52
+ {
53
+ "name": "doctrine/instantiator",
54
+ "version": "1.0.4",
55
+ "source": {
56
+ "type": "git",
57
+ "url": "https://github.com/doctrine/instantiator.git",
58
+ "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119"
59
+ },
60
+ "dist": {
61
+ "type": "zip",
62
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119",
63
+ "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119",
64
+ "shasum": ""
65
+ },
66
+ "require": {
67
+ "php": ">=5.3,<8.0-DEV"
68
+ },
69
+ "require-dev": {
70
+ "athletic/athletic": "~0.1.8",
71
+ "ext-pdo": "*",
72
+ "ext-phar": "*",
73
+ "phpunit/phpunit": "~4.0",
74
+ "squizlabs/php_codesniffer": "2.0.*@ALPHA"
75
+ },
76
+ "type": "library",
77
+ "extra": {
78
+ "branch-alias": {
79
+ "dev-master": "1.0.x-dev"
80
+ }
81
+ },
82
+ "autoload": {
83
+ "psr-0": {
84
+ "Doctrine\\Instantiator\\": "src"
85
+ }
86
+ },
87
+ "notification-url": "https://packagist.org/downloads/",
88
+ "license": [
89
+ "MIT"
90
+ ],
91
+ "authors": [
92
+ {
93
+ "name": "Marco Pivetta",
94
+ "email": "ocramius@gmail.com",
95
+ "homepage": "http://ocramius.github.com/"
96
+ }
97
+ ],
98
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
99
+ "homepage": "https://github.com/doctrine/instantiator",
100
+ "keywords": [
101
+ "constructor",
102
+ "instantiate"
103
+ ],
104
+ "time": "2014-10-13 12:58:55"
105
+ },
106
+ {
107
+ "name": "hamcrest/hamcrest-php",
108
+ "version": "v1.2.2",
109
+ "source": {
110
+ "type": "git",
111
+ "url": "https://github.com/hamcrest/hamcrest-php.git",
112
+ "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c"
113
+ },
114
+ "dist": {
115
+ "type": "zip",
116
+ "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c",
117
+ "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c",
118
+ "shasum": ""
119
+ },
120
+ "require": {
121
+ "php": ">=5.3.2"
122
+ },
123
+ "replace": {
124
+ "cordoval/hamcrest-php": "*",
125
+ "davedevelopment/hamcrest-php": "*",
126
+ "kodova/hamcrest-php": "*"
127
+ },
128
+ "require-dev": {
129
+ "phpunit/php-file-iterator": "1.3.3",
130
+ "satooshi/php-coveralls": "dev-master"
131
+ },
132
+ "type": "library",
133
+ "autoload": {
134
+ "classmap": [
135
+ "hamcrest"
136
+ ],
137
+ "files": [
138
+ "hamcrest/Hamcrest.php"
139
+ ]
140
+ },
141
+ "notification-url": "https://packagist.org/downloads/",
142
+ "license": [
143
+ "BSD"
144
+ ],
145
+ "description": "This is the PHP port of Hamcrest Matchers",
146
+ "keywords": [
147
+ "test"
148
+ ],
149
+ "time": "2015-05-11 14:41:42"
150
+ },
151
+ {
152
+ "name": "mikey179/vfsStream",
153
+ "version": "v1.5.0",
154
+ "source": {
155
+ "type": "git",
156
+ "url": "https://github.com/mikey179/vfsStream.git",
157
+ "reference": "4dc0d2f622412f561f5b242b19b98068bbbc883a"
158
+ },
159
+ "dist": {
160
+ "type": "zip",
161
+ "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/4dc0d2f622412f561f5b242b19b98068bbbc883a",
162
+ "reference": "4dc0d2f622412f561f5b242b19b98068bbbc883a",
163
+ "shasum": ""
164
+ },
165
+ "require": {
166
+ "php": ">=5.3.0"
167
+ },
168
+ "require-dev": {
169
+ "phpunit/phpunit": "~4.5"
170
+ },
171
+ "type": "library",
172
+ "extra": {
173
+ "branch-alias": {
174
+ "dev-master": "1.5.x-dev"
175
+ }
176
+ },
177
+ "autoload": {
178
+ "psr-0": {
179
+ "org\\bovigo\\vfs\\": "src/main/php"
180
+ }
181
+ },
182
+ "notification-url": "https://packagist.org/downloads/",
183
+ "license": [
184
+ "BSD-3-Clause"
185
+ ],
186
+ "authors": [
187
+ {
188
+ "name": "Frank Kleine",
189
+ "homepage": "http://frankkleine.de/",
190
+ "role": "Developer"
191
+ }
192
+ ],
193
+ "description": "Virtual file system to mock the real file system in unit tests.",
194
+ "homepage": "http://vfs.bovigo.org/",
195
+ "time": "2015-03-29 11:19:49"
196
+ },
197
  {
198
  "name": "mockery/mockery",
199
+ "version": "0.9.4",
200
  "source": {
201
  "type": "git",
202
  "url": "https://github.com/padraic/mockery.git",
203
+ "reference": "70bba85e4aabc9449626651f48b9018ede04f86b"
204
  },
205
  "dist": {
206
  "type": "zip",
207
+ "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b",
208
+ "reference": "70bba85e4aabc9449626651f48b9018ede04f86b",
209
  "shasum": ""
210
  },
211
  "require": {
212
+ "hamcrest/hamcrest-php": "~1.1",
213
  "lib-pcre": ">=7.0",
214
  "php": ">=5.3.2"
215
  },
216
  "require-dev": {
217
+ "phpunit/phpunit": "~4.0"
 
 
218
  },
219
  "type": "library",
220
  "extra": {
257
  "test double",
258
  "testing"
259
  ],
260
+ "time": "2015-04-02 19:54:00"
261
+ },
262
+ {
263
+ "name": "phpdocumentor/reflection-docblock",
264
+ "version": "2.0.4",
265
+ "source": {
266
+ "type": "git",
267
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
268
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
269
+ },
270
+ "dist": {
271
+ "type": "zip",
272
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
273
+ "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
274
+ "shasum": ""
275
+ },
276
+ "require": {
277
+ "php": ">=5.3.3"
278
+ },
279
+ "require-dev": {
280
+ "phpunit/phpunit": "~4.0"
281
+ },
282
+ "suggest": {
283
+ "dflydev/markdown": "~1.0",
284
+ "erusev/parsedown": "~1.0"
285
+ },
286
+ "type": "library",
287
+ "extra": {
288
+ "branch-alias": {
289
+ "dev-master": "2.0.x-dev"
290
+ }
291
+ },
292
+ "autoload": {
293
+ "psr-0": {
294
+ "phpDocumentor": [
295
+ "src/"
296
+ ]
297
+ }
298
+ },
299
+ "notification-url": "https://packagist.org/downloads/",
300
+ "license": [
301
+ "MIT"
302
+ ],
303
+ "authors": [
304
+ {
305
+ "name": "Mike van Riel",
306
+ "email": "mike.vanriel@naenius.com"
307
+ }
308
+ ],
309
+ "time": "2015-02-03 12:10:50"
310
+ },
311
+ {
312
+ "name": "phpspec/prophecy",
313
+ "version": "v1.4.1",
314
+ "source": {
315
+ "type": "git",
316
+ "url": "https://github.com/phpspec/prophecy.git",
317
+ "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373"
318
+ },
319
+ "dist": {
320
+ "type": "zip",
321
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
322
+ "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
323
+ "shasum": ""
324
+ },
325
+ "require": {
326
+ "doctrine/instantiator": "^1.0.2",
327
+ "phpdocumentor/reflection-docblock": "~2.0",
328
+ "sebastian/comparator": "~1.1"
329
+ },
330
+ "require-dev": {
331
+ "phpspec/phpspec": "~2.0"
332
+ },
333
+ "type": "library",
334
+ "extra": {
335
+ "branch-alias": {
336
+ "dev-master": "1.4.x-dev"
337
+ }
338
+ },
339
+ "autoload": {
340
+ "psr-0": {
341
+ "Prophecy\\": "src/"
342
+ }
343
+ },
344
+ "notification-url": "https://packagist.org/downloads/",
345
+ "license": [
346
+ "MIT"
347
+ ],
348
+ "authors": [
349
+ {
350
+ "name": "Konstantin Kudryashov",
351
+ "email": "ever.zet@gmail.com",
352
+ "homepage": "http://everzet.com"
353
+ },
354
+ {
355
+ "name": "Marcello Duarte",
356
+ "email": "marcello.duarte@gmail.com"
357
+ }
358
+ ],
359
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
360
+ "homepage": "https://github.com/phpspec/prophecy",
361
+ "keywords": [
362
+ "Double",
363
+ "Dummy",
364
+ "fake",
365
+ "mock",
366
+ "spy",
367
+ "stub"
368
+ ],
369
+ "time": "2015-04-27 22:15:08"
370
+ },
371
+ {
372
+ "name": "phpunit/php-code-coverage",
373
+ "version": "2.0.16",
374
+ "source": {
375
+ "type": "git",
376
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
377
+ "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c"
378
+ },
379
+ "dist": {
380
+ "type": "zip",
381
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c",
382
+ "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c",
383
+ "shasum": ""
384
+ },
385
+ "require": {
386
+ "php": ">=5.3.3",
387
+ "phpunit/php-file-iterator": "~1.3",
388
+ "phpunit/php-text-template": "~1.2",
389
+ "phpunit/php-token-stream": "~1.3",
390
+ "sebastian/environment": "~1.0",
391
+ "sebastian/version": "~1.0"
392
+ },
393
+ "require-dev": {
394
+ "ext-xdebug": ">=2.1.4",
395
+ "phpunit/phpunit": "~4"
396
+ },
397
+ "suggest": {
398
+ "ext-dom": "*",
399
+ "ext-xdebug": ">=2.2.1",
400
+ "ext-xmlwriter": "*"
401
+ },
402
+ "type": "library",
403
+ "extra": {
404
+ "branch-alias": {
405
+ "dev-master": "2.0.x-dev"
406
+ }
407
+ },
408
+ "autoload": {
409
+ "classmap": [
410
+ "src/"
411
+ ]
412
+ },
413
+ "notification-url": "https://packagist.org/downloads/",
414
+ "license": [
415
+ "BSD-3-Clause"
416
+ ],
417
+ "authors": [
418
+ {
419
+ "name": "Sebastian Bergmann",
420
+ "email": "sb@sebastian-bergmann.de",
421
+ "role": "lead"
422
+ }
423
+ ],
424
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
425
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
426
+ "keywords": [
427
+ "coverage",
428
+ "testing",
429
+ "xunit"
430
+ ],
431
+ "time": "2015-04-11 04:35:00"
432
+ },
433
+ {
434
+ "name": "phpunit/php-file-iterator",
435
+ "version": "1.4.0",
436
+ "source": {
437
+ "type": "git",
438
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
439
+ "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb"
440
+ },
441
+ "dist": {
442
+ "type": "zip",
443
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb",
444
+ "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb",
445
+ "shasum": ""
446
+ },
447
+ "require": {
448
+ "php": ">=5.3.3"
449
+ },
450
+ "type": "library",
451
+ "extra": {
452
+ "branch-alias": {
453
+ "dev-master": "1.4.x-dev"
454
+ }
455
+ },
456
+ "autoload": {
457
+ "classmap": [
458
+ "src/"
459
+ ]
460
+ },
461
+ "notification-url": "https://packagist.org/downloads/",
462
+ "license": [
463
+ "BSD-3-Clause"
464
+ ],
465
+ "authors": [
466
+ {
467
+ "name": "Sebastian Bergmann",
468
+ "email": "sb@sebastian-bergmann.de",
469
+ "role": "lead"
470
+ }
471
+ ],
472
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
473
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
474
+ "keywords": [
475
+ "filesystem",
476
+ "iterator"
477
+ ],
478
+ "time": "2015-04-02 05:19:05"
479
+ },
480
+ {
481
+ "name": "phpunit/php-text-template",
482
+ "version": "1.2.0",
483
+ "source": {
484
+ "type": "git",
485
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
486
+ "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a"
487
+ },
488
+ "dist": {
489
+ "type": "zip",
490
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
491
+ "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a",
492
+ "shasum": ""
493
+ },
494
+ "require": {
495
+ "php": ">=5.3.3"
496
+ },
497
+ "type": "library",
498
+ "autoload": {
499
+ "classmap": [
500
+ "Text/"
501
+ ]
502
+ },
503
+ "notification-url": "https://packagist.org/downloads/",
504
+ "include-path": [
505
+ ""
506
+ ],
507
+ "license": [
508
+ "BSD-3-Clause"
509
+ ],
510
+ "authors": [
511
+ {
512
+ "name": "Sebastian Bergmann",
513
+ "email": "sb@sebastian-bergmann.de",
514
+ "role": "lead"
515
+ }
516
+ ],
517
+ "description": "Simple template engine.",
518
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
519
+ "keywords": [
520
+ "template"
521
+ ],
522
+ "time": "2014-01-30 17:20:04"
523
+ },
524
+ {
525
+ "name": "phpunit/php-timer",
526
+ "version": "1.0.5",
527
+ "source": {
528
+ "type": "git",
529
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
530
+ "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
531
+ },
532
+ "dist": {
533
+ "type": "zip",
534
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
535
+ "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
536
+ "shasum": ""
537
+ },
538
+ "require": {
539
+ "php": ">=5.3.3"
540
+ },
541
+ "type": "library",
542
+ "autoload": {
543
+ "classmap": [
544
+ "PHP/"
545
+ ]
546
+ },
547
+ "notification-url": "https://packagist.org/downloads/",
548
+ "include-path": [
549
+ ""
550
+ ],
551
+ "license": [
552
+ "BSD-3-Clause"
553
+ ],
554
+ "authors": [
555
+ {
556
+ "name": "Sebastian Bergmann",
557
+ "email": "sb@sebastian-bergmann.de",
558
+ "role": "lead"
559
+ }
560
+ ],
561
+ "description": "Utility class for timing",
562
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
563
+ "keywords": [
564
+ "timer"
565
+ ],
566
+ "time": "2013-08-02 07:42:54"
567
+ },
568
+ {
569
+ "name": "phpunit/php-token-stream",
570
+ "version": "1.4.1",
571
+ "source": {
572
+ "type": "git",
573
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
574
+ "reference": "eab81d02569310739373308137284e0158424330"
575
+ },
576
+ "dist": {
577
+ "type": "zip",
578
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
579
+ "reference": "eab81d02569310739373308137284e0158424330",
580
+ "shasum": ""
581
+ },
582
+ "require": {
583
+ "ext-tokenizer": "*",
584
+ "php": ">=5.3.3"
585
+ },
586
+ "require-dev": {
587
+ "phpunit/phpunit": "~4.2"
588
+ },
589
+ "type": "library",
590
+ "extra": {
591
+ "branch-alias": {
592
+ "dev-master": "1.4-dev"
593
+ }
594
+ },
595
+ "autoload": {
596
+ "classmap": [
597
+ "src/"
598
+ ]
599
+ },
600
+ "notification-url": "https://packagist.org/downloads/",
601
+ "license": [
602
+ "BSD-3-Clause"
603
+ ],
604
+ "authors": [
605
+ {
606
+ "name": "Sebastian Bergmann",
607
+ "email": "sebastian@phpunit.de"
608
+ }
609
+ ],
610
+ "description": "Wrapper around PHP's tokenizer extension.",
611
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
612
+ "keywords": [
613
+ "tokenizer"
614
+ ],
615
+ "time": "2015-04-08 04:46:07"
616
+ },
617
+ {
618
+ "name": "phpunit/phpunit",
619
+ "version": "4.6.6",
620
+ "source": {
621
+ "type": "git",
622
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
623
+ "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac"
624
+ },
625
+ "dist": {
626
+ "type": "zip",
627
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac",
628
+ "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac",
629
+ "shasum": ""
630
+ },
631
+ "require": {
632
+ "ext-dom": "*",
633
+ "ext-json": "*",
634
+ "ext-pcre": "*",
635
+ "ext-reflection": "*",
636
+ "ext-spl": "*",
637
+ "php": ">=5.3.3",
638
+ "phpspec/prophecy": "~1.3,>=1.3.1",
639
+ "phpunit/php-code-coverage": "~2.0,>=2.0.11",
640
+ "phpunit/php-file-iterator": "~1.4",
641
+ "phpunit/php-text-template": "~1.2",
642
+ "phpunit/php-timer": "~1.0",
643
+ "phpunit/phpunit-mock-objects": "~2.3",
644
+ "sebastian/comparator": "~1.1",
645
+ "sebastian/diff": "~1.2",
646
+ "sebastian/environment": "~1.2",
647
+ "sebastian/exporter": "~1.2",
648
+ "sebastian/global-state": "~1.0",
649
+ "sebastian/version": "~1.0",
650
+ "symfony/yaml": "~2.1|~3.0"
651
+ },
652
+ "suggest": {
653
+ "phpunit/php-invoker": "~1.1"
654
+ },
655
+ "bin": [
656
+ "phpunit"
657
+ ],
658
+ "type": "library",
659
+ "extra": {
660
+ "branch-alias": {
661
+ "dev-master": "4.6.x-dev"
662
+ }
663
+ },
664
+ "autoload": {
665
+ "classmap": [
666
+ "src/"
667
+ ]
668
+ },
669
+ "notification-url": "https://packagist.org/downloads/",
670
+ "license": [
671
+ "BSD-3-Clause"
672
+ ],
673
+ "authors": [
674
+ {
675
+ "name": "Sebastian Bergmann",
676
+ "email": "sebastian@phpunit.de",
677
+ "role": "lead"
678
+ }
679
+ ],
680
+ "description": "The PHP Unit Testing framework.",
681
+ "homepage": "https://phpunit.de/",
682
+ "keywords": [
683
+ "phpunit",
684
+ "testing",
685
+ "xunit"
686
+ ],
687
+ "time": "2015-04-29 15:18:52"
688
+ },
689
+ {
690
+ "name": "phpunit/phpunit-mock-objects",
691
+ "version": "2.3.1",
692
+ "source": {
693
+ "type": "git",
694
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
695
+ "reference": "74ffb87f527f24616f72460e54b595f508dccb5c"
696
+ },
697
+ "dist": {
698
+ "type": "zip",
699
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c",
700
+ "reference": "74ffb87f527f24616f72460e54b595f508dccb5c",
701
+ "shasum": ""
702
+ },
703
+ "require": {
704
+ "doctrine/instantiator": "~1.0,>=1.0.2",
705
+ "php": ">=5.3.3",
706
+ "phpunit/php-text-template": "~1.2"
707
+ },
708
+ "require-dev": {
709
+ "phpunit/phpunit": "~4.4"
710
+ },
711
+ "suggest": {
712
+ "ext-soap": "*"
713
+ },
714
+ "type": "library",
715
+ "extra": {
716
+ "branch-alias": {
717
+ "dev-master": "2.3.x-dev"
718
+ }
719
+ },
720
+ "autoload": {
721
+ "classmap": [
722
+ "src/"
723
+ ]
724
+ },
725
+ "notification-url": "https://packagist.org/downloads/",
726
+ "license": [
727
+ "BSD-3-Clause"
728
+ ],
729
+ "authors": [
730
+ {
731
+ "name": "Sebastian Bergmann",
732
+ "email": "sb@sebastian-bergmann.de",
733
+ "role": "lead"
734
+ }
735
+ ],
736
+ "description": "Mock Object library for PHPUnit",
737
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
738
+ "keywords": [
739
+ "mock",
740
+ "xunit"
741
+ ],
742
+ "time": "2015-04-02 05:36:41"
743
+ },
744
+ {
745
+ "name": "sebastian/comparator",
746
+ "version": "1.1.1",
747
+ "source": {
748
+ "type": "git",
749
+ "url": "https://github.com/sebastianbergmann/comparator.git",
750
+ "reference": "1dd8869519a225f7f2b9eb663e225298fade819e"
751
+ },
752
+ "dist": {
753
+ "type": "zip",
754
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e",
755
+ "reference": "1dd8869519a225f7f2b9eb663e225298fade819e",
756
+ "shasum": ""
757
+ },
758
+ "require": {
759
+ "php": ">=5.3.3",
760
+ "sebastian/diff": "~1.2",
761
+ "sebastian/exporter": "~1.2"
762
+ },
763
+ "require-dev": {
764
+ "phpunit/phpunit": "~4.4"
765
+ },
766
+ "type": "library",
767
+ "extra": {
768
+ "branch-alias": {
769
+ "dev-master": "1.1.x-dev"
770
+ }
771
+ },
772
+ "autoload": {
773
+ "classmap": [
774
+ "src/"
775
+ ]
776
+ },
777
+ "notification-url": "https://packagist.org/downloads/",
778
+ "license": [
779
+ "BSD-3-Clause"
780
+ ],
781
+ "authors": [
782
+ {
783
+ "name": "Jeff Welch",
784
+ "email": "whatthejeff@gmail.com"
785
+ },
786
+ {
787
+ "name": "Volker Dusch",
788
+ "email": "github@wallbash.com"
789
+ },
790
+ {
791
+ "name": "Bernhard Schussek",
792
+ "email": "bschussek@2bepublished.at"
793
+ },
794
+ {
795
+ "name": "Sebastian Bergmann",
796
+ "email": "sebastian@phpunit.de"
797
+ }
798
+ ],
799
+ "description": "Provides the functionality to compare PHP values for equality",
800
+ "homepage": "http://www.github.com/sebastianbergmann/comparator",
801
+ "keywords": [
802
+ "comparator",
803
+ "compare",
804
+ "equality"
805
+ ],
806
+ "time": "2015-01-29 16:28:08"
807
+ },
808
+ {
809
+ "name": "sebastian/diff",
810
+ "version": "1.3.0",
811
+ "source": {
812
+ "type": "git",
813
+ "url": "https://github.com/sebastianbergmann/diff.git",
814
+ "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
815
+ },
816
+ "dist": {
817
+ "type": "zip",
818
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
819
+ "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
820
+ "shasum": ""
821
+ },
822
+ "require": {
823
+ "php": ">=5.3.3"
824
+ },
825
+ "require-dev": {
826
+ "phpunit/phpunit": "~4.2"
827
+ },
828
+ "type": "library",
829
+ "extra": {
830
+ "branch-alias": {
831
+ "dev-master": "1.3-dev"
832
+ }
833
+ },
834
+ "autoload": {
835
+ "classmap": [
836
+ "src/"
837
+ ]
838
+ },
839
+ "notification-url": "https://packagist.org/downloads/",
840
+ "license": [
841
+ "BSD-3-Clause"
842
+ ],
843
+ "authors": [
844
+ {
845
+ "name": "Kore Nordmann",
846
+ "email": "mail@kore-nordmann.de"
847
+ },
848
+ {
849
+ "name": "Sebastian Bergmann",
850
+ "email": "sebastian@phpunit.de"
851
+ }
852
+ ],
853
+ "description": "Diff implementation",
854
+ "homepage": "http://www.github.com/sebastianbergmann/diff",
855
+ "keywords": [
856
+ "diff"
857
+ ],
858
+ "time": "2015-02-22 15:13:53"
859
+ },
860
+ {
861
+ "name": "sebastian/environment",
862
+ "version": "1.2.2",
863
+ "source": {
864
+ "type": "git",
865
+ "url": "https://github.com/sebastianbergmann/environment.git",
866
+ "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e"
867
+ },
868
+ "dist": {
869
+ "type": "zip",
870
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e",
871
+ "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e",
872
+ "shasum": ""
873
+ },
874
+ "require": {
875
+ "php": ">=5.3.3"
876
+ },
877
+ "require-dev": {
878
+ "phpunit/phpunit": "~4.4"
879
+ },
880
+ "type": "library",
881
+ "extra": {
882
+ "branch-alias": {
883
+ "dev-master": "1.3.x-dev"
884
+ }
885
+ },
886
+ "autoload": {
887
+ "classmap": [
888
+ "src/"
889
+ ]
890
+ },
891
+ "notification-url": "https://packagist.org/downloads/",
892
+ "license": [
893
+ "BSD-3-Clause"
894
+ ],
895
+ "authors": [
896
+ {
897
+ "name": "Sebastian Bergmann",
898
+ "email": "sebastian@phpunit.de"
899
+ }
900
+ ],
901
+ "description": "Provides functionality to handle HHVM/PHP environments",
902
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
903
+ "keywords": [
904
+ "Xdebug",
905
+ "environment",
906
+ "hhvm"
907
+ ],
908
+ "time": "2015-01-01 10:01:08"
909
+ },
910
+ {
911
+ "name": "sebastian/exporter",
912
+ "version": "1.2.0",
913
+ "source": {
914
+ "type": "git",
915
+ "url": "https://github.com/sebastianbergmann/exporter.git",
916
+ "reference": "84839970d05254c73cde183a721c7af13aede943"
917
+ },
918
+ "dist": {
919
+ "type": "zip",
920
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943",
921
+ "reference": "84839970d05254c73cde183a721c7af13aede943",
922
+ "shasum": ""
923
+ },
924
+ "require": {
925
+ "php": ">=5.3.3",
926
+ "sebastian/recursion-context": "~1.0"
927
+ },
928
+ "require-dev": {
929
+ "phpunit/phpunit": "~4.4"
930
+ },
931
+ "type": "library",
932
+ "extra": {
933
+ "branch-alias": {
934
+ "dev-master": "1.2.x-dev"
935
+ }
936
+ },
937
+ "autoload": {
938
+ "classmap": [
939
+ "src/"
940
+ ]
941
+ },
942
+ "notification-url": "https://packagist.org/downloads/",
943
+ "license": [
944
+ "BSD-3-Clause"
945
+ ],
946
+ "authors": [
947
+ {
948
+ "name": "Jeff Welch",
949
+ "email": "whatthejeff@gmail.com"
950
+ },
951
+ {
952
+ "name": "Volker Dusch",
953
+ "email": "github@wallbash.com"
954
+ },
955
+ {
956
+ "name": "Bernhard Schussek",
957
+ "email": "bschussek@2bepublished.at"
958
+ },
959
+ {
960
+ "name": "Sebastian Bergmann",
961
+ "email": "sebastian@phpunit.de"
962
+ },
963
+ {
964
+ "name": "Adam Harvey",
965
+ "email": "aharvey@php.net"
966
+ }
967
+ ],
968
+ "description": "Provides the functionality to export PHP variables for visualization",
969
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
970
+ "keywords": [
971
+ "export",
972
+ "exporter"
973
+ ],
974
+ "time": "2015-01-27 07:23:06"
975
+ },
976
+ {
977
+ "name": "sebastian/global-state",
978
+ "version": "1.0.0",
979
+ "source": {
980
+ "type": "git",
981
+ "url": "https://github.com/sebastianbergmann/global-state.git",
982
+ "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01"
983
+ },
984
+ "dist": {
985
+ "type": "zip",
986
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
987
+ "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
988
+ "shasum": ""
989
+ },
990
+ "require": {
991
+ "php": ">=5.3.3"
992
+ },
993
+ "require-dev": {
994
+ "phpunit/phpunit": "~4.2"
995
+ },
996
+ "suggest": {
997
+ "ext-uopz": "*"
998
+ },
999
+ "type": "library",
1000
+ "extra": {
1001
+ "branch-alias": {
1002
+ "dev-master": "1.0-dev"
1003
+ }
1004
+ },
1005
+ "autoload": {
1006
+ "classmap": [
1007
+ "src/"
1008
+ ]
1009
+ },
1010
+ "notification-url": "https://packagist.org/downloads/",
1011
+ "license": [
1012
+ "BSD-3-Clause"
1013
+ ],
1014
+ "authors": [
1015
+ {
1016
+ "name": "Sebastian Bergmann",
1017
+ "email": "sebastian@phpunit.de"
1018
+ }
1019
+ ],
1020
+ "description": "Snapshotting of global state",
1021
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
1022
+ "keywords": [
1023
+ "global state"
1024
+ ],
1025
+ "time": "2014-10-06 09:23:50"
1026
+ },
1027
+ {
1028
+ "name": "sebastian/recursion-context",
1029
+ "version": "1.0.0",
1030
+ "source": {
1031
+ "type": "git",
1032
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
1033
+ "reference": "3989662bbb30a29d20d9faa04a846af79b276252"
1034
+ },
1035
+ "dist": {
1036
+ "type": "zip",
1037
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252",
1038
+ "reference": "3989662bbb30a29d20d9faa04a846af79b276252",
1039
+ "shasum": ""
1040
+ },
1041
+ "require": {
1042
+ "php": ">=5.3.3"
1043
+ },
1044
+ "require-dev": {
1045
+ "phpunit/phpunit": "~4.4"
1046
+ },
1047
+ "type": "library",
1048
+ "extra": {
1049
+ "branch-alias": {
1050
+ "dev-master": "1.0.x-dev"
1051
+ }
1052
+ },
1053
+ "autoload": {
1054
+ "classmap": [
1055
+ "src/"
1056
+ ]
1057
+ },
1058
+ "notification-url": "https://packagist.org/downloads/",
1059
+ "license": [
1060
+ "BSD-3-Clause"
1061
+ ],
1062
+ "authors": [
1063
+ {
1064
+ "name": "Jeff Welch",
1065
+ "email": "whatthejeff@gmail.com"
1066
+ },
1067
+ {
1068
+ "name": "Sebastian Bergmann",
1069
+ "email": "sebastian@phpunit.de"
1070
+ },
1071
+ {
1072
+ "name": "Adam Harvey",
1073
+ "email": "aharvey@php.net"
1074
+ }
1075
+ ],
1076
+ "description": "Provides functionality to recursively process PHP variables",
1077
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1078
+ "time": "2015-01-24 09:48:32"
1079
+ },
1080
+ {
1081
+ "name": "sebastian/version",
1082
+ "version": "1.0.5",
1083
+ "source": {
1084
+ "type": "git",
1085
+ "url": "https://github.com/sebastianbergmann/version.git",
1086
+ "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4"
1087
+ },
1088
+ "dist": {
1089
+ "type": "zip",
1090
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
1091
+ "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
1092
+ "shasum": ""
1093
+ },
1094
+ "type": "library",
1095
+ "autoload": {
1096
+ "classmap": [
1097
+ "src/"
1098
+ ]
1099
+ },
1100
+ "notification-url": "https://packagist.org/downloads/",
1101
+ "license": [
1102
+ "BSD-3-Clause"
1103
+ ],
1104
+ "authors": [
1105
+ {
1106
+ "name": "Sebastian Bergmann",
1107
+ "email": "sebastian@phpunit.de",
1108
+ "role": "lead"
1109
+ }
1110
+ ],
1111
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1112
+ "homepage": "https://github.com/sebastianbergmann/version",
1113
+ "time": "2015-02-24 06:35:25"
1114
+ },
1115
+ {
1116
+ "name": "symfony/yaml",
1117
+ "version": "v2.6.7",
1118
+ "target-dir": "Symfony/Component/Yaml",
1119
+ "source": {
1120
+ "type": "git",
1121
+ "url": "https://github.com/symfony/Yaml.git",
1122
+ "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2"
1123
+ },
1124
+ "dist": {
1125
+ "type": "zip",
1126
+ "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2",
1127
+ "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2",
1128
+ "shasum": ""
1129
+ },
1130
+ "require": {
1131
+ "php": ">=5.3.3"
1132
+ },
1133
+ "require-dev": {
1134
+ "symfony/phpunit-bridge": "~2.7"
1135
+ },
1136
+ "type": "library",
1137
+ "extra": {
1138
+ "branch-alias": {
1139
+ "dev-master": "2.6-dev"
1140
+ }
1141
+ },
1142
+ "autoload": {
1143
+ "psr-0": {
1144
+ "Symfony\\Component\\Yaml\\": ""
1145
+ }
1146
+ },
1147
+ "notification-url": "https://packagist.org/downloads/",
1148
+ "license": [
1149
+ "MIT"
1150
+ ],
1151
+ "authors": [
1152
+ {
1153
+ "name": "Fabien Potencier",
1154
+ "email": "fabien@symfony.com"
1155
+ },
1156
+ {
1157
+ "name": "Symfony Community",
1158
+ "homepage": "https://symfony.com/contributors"
1159
+ }
1160
+ ],
1161
+ "description": "Symfony Yaml Component",
1162
+ "homepage": "https://symfony.com",
1163
+ "time": "2015-05-02 15:18:45"
1164
  }
1165
  ],
1166
  "aliases": [],
1167
  "minimum-stability": "stable",
1168
+ "stability-flags": [],
 
 
1169
  "prefer-stable": false,
1170
+ "prefer-lowest": false,
1171
  "platform": [],
1172
  "platform-dev": []
1173
  }
config/Dockerfile-wordpress-30 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 f75f2e74a80213608c798add216d137c7dfbd86a
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-31 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 b93ff680a7035378abac1063abebf72a473e8a78
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-32 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 674bcf0abe80770ac08dfb4c5f21df3303bf771a
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-33 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 ea7c91903df3090d8e90ef4e26945def46437a37
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  # Fix empty dashboard bug (http://wordpress.stackexchange.com/questions/127427/how-to-fix-empty-dashboard-issue-in-wordpress).
16
  RUN sed -i '706s/self::$this/$this/' /usr/src/wordpress/wp-admin/includes/screen.php
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  # Fix empty dashboard bug (http://wordpress.stackexchange.com/questions/127427/how-to-fix-empty-dashboard-issue-in-wordpress).
17
  RUN sed -i '706s/self::$this/$this/' /usr/src/wordpress/wp-admin/includes/screen.php
config/Dockerfile-wordpress-34 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 11d130c06ba9c55e7aa80c04c249a4f1b19accd6
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-35 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 f75e9aadb1c2f754e89aacdfb5ab72bbfb10678d
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-36 CHANGED
@@ -10,7 +10,8 @@ ENV WORDPRESS_SHA1 a1ad687776a9348e85b9f9603b4d227e433ef697
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-37 CHANGED
@@ -2,15 +2,16 @@ FROM wordpress:4
2
 
3
  RUN docker-php-ext-install mysql
4
 
5
- ENV WORDPRESS_VERSION 3.7.5
6
- ENV WORDPRESS_UPSTREAM_VERSION 3.7.5
7
- ENV WORDPRESS_SHA1 b2c762558c9688532fe465b7916ba65039015599
8
 
9
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
2
 
3
  RUN docker-php-ext-install mysql
4
 
5
+ ENV WORDPRESS_VERSION 3.7.8
6
+ ENV WORDPRESS_UPSTREAM_VERSION 3.7.8
7
+ ENV WORDPRESS_SHA1 f6a326bc7fe8805a142d3c3e5db7857c336d8a75
8
 
9
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-38 CHANGED
@@ -2,15 +2,16 @@ FROM wordpress:4
2
 
3
  RUN docker-php-ext-install mysql
4
 
5
- ENV WORDPRESS_VERSION 3.8.5
6
- ENV WORDPRESS_UPSTREAM_VERSION 3.8.5
7
- ENV WORDPRESS_SHA1 70b02580c1045eb854cfa94ef9bea73fdffe62eb
8
 
9
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
- && rm wordpress.tar.gz
 
14
 
15
  ENTRYPOINT ["/entrypoint.sh"]
16
  CMD ["apache2-foreground"]
2
 
3
  RUN docker-php-ext-install mysql
4
 
5
+ ENV WORDPRESS_VERSION 3.8.8
6
+ ENV WORDPRESS_UPSTREAM_VERSION 3.8.8
7
+ ENV WORDPRESS_SHA1 8c5875ae76cdc9fb545e9e30591c67021bb1fafd
8
 
9
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
10
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
11
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
12
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
13
+ && rm wordpress.tar.gz \
14
+ && chown -R www-data:www-data /usr/src/wordpress
15
 
16
  ENTRYPOINT ["/entrypoint.sh"]
17
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-39 CHANGED
@@ -1,14 +1,15 @@
1
  FROM wordpress:4
2
 
3
- ENV WORDPRESS_VERSION 3.9.3
4
- ENV WORDPRESS_UPSTREAM_VERSION 3.9.3
5
- ENV WORDPRESS_SHA1 77c150646b732587a5acbe9daf3b164901dba991
6
 
7
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
- && rm wordpress.tar.gz
 
12
 
13
  ENTRYPOINT ["/entrypoint.sh"]
14
  CMD ["apache2-foreground"]
1
  FROM wordpress:4
2
 
3
+ ENV WORDPRESS_VERSION 3.9.6
4
+ ENV WORDPRESS_UPSTREAM_VERSION 3.9.6
5
+ ENV WORDPRESS_SHA1 373c185080d0e3b2cd748277d013894e8a3af0d9
6
 
7
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
+ && rm wordpress.tar.gz \
12
+ && chown -R www-data:www-data /usr/src/wordpress
13
 
14
  ENTRYPOINT ["/entrypoint.sh"]
15
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-40 CHANGED
@@ -1,14 +1,15 @@
1
  FROM wordpress:4
2
 
3
- ENV WORDPRESS_VERSION 4.0.1
4
- ENV WORDPRESS_UPSTREAM_VERSION 4.0.1
5
- ENV WORDPRESS_SHA1 ef1bd7ca90b67e6d8f46dc2e2a78c0ec4c2afb40
6
 
7
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
- && rm wordpress.tar.gz
 
12
 
13
  ENTRYPOINT ["/entrypoint.sh"]
14
  CMD ["apache2-foreground"]
1
  FROM wordpress:4
2
 
3
+ ENV WORDPRESS_VERSION 4.0.5
4
+ ENV WORDPRESS_UPSTREAM_VERSION 4.0.5
5
+ ENV WORDPRESS_SHA1 23de8e24ea68a19723b6ebc95f44c8d32df97a8e
6
 
7
  # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
  RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
  && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
  && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
+ && rm wordpress.tar.gz \
12
+ && chown -R www-data:www-data /usr/src/wordpress
13
 
14
  ENTRYPOINT ["/entrypoint.sh"]
15
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-41 CHANGED
@@ -1,8 +1,15 @@
1
  FROM wordpress:4
2
 
3
- ENV WORDPRESS_VERSION 4.1
4
- ENV WORDPRESS_UPSTREAM_VERSION 4.1
5
- ENV WORDPRESS_SHA1 f0437c96ae3d8acaba3579566f1346f4cd06468e
 
 
 
 
 
 
 
6
 
7
  ENTRYPOINT ["/entrypoint.sh"]
8
  CMD ["apache2-foreground"]
1
  FROM wordpress:4
2
 
3
+ ENV WORDPRESS_VERSION 4.1.5
4
+ ENV WORDPRESS_UPSTREAM_VERSION 4.1.5
5
+ ENV WORDPRESS_SHA1 85bc3f20d0ee8c98f9eabeba48eb37fe732eab33
6
+
7
+ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
+ RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
+ && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
+ && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
+ && rm wordpress.tar.gz \
12
+ && chown -R www-data:www-data /usr/src/wordpress
13
 
14
  ENTRYPOINT ["/entrypoint.sh"]
15
  CMD ["apache2-foreground"]
config/Dockerfile-wordpress-42 ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM wordpress:4
2
+
3
+ ENV WORDPRESS_VERSION 4.2.2
4
+ ENV WORDPRESS_UPSTREAM_VERSION 4.2.2
5
+ ENV WORDPRESS_SHA1 d3a70d0f116e6afea5b850f793a81a97d2115039
6
+
7
+ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress
8
+ RUN curl -o wordpress.tar.gz -sSL https://wordpress.org/wordpress-${WORDPRESS_UPSTREAM_VERSION}.tar.gz \
9
+ && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \
10
+ && tar -xzf wordpress.tar.gz -C /usr/src/ \
11
+ && rm wordpress.tar.gz \
12
+ && chown -R www-data:www-data /usr/src/wordpress
13
+
14
+ ENTRYPOINT ["/entrypoint.sh"]
15
+ CMD ["apache2-foreground"]
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://tinypng.com/
4
  Tags: compress, optimize, shrink, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, faster, performance, panda
5
  Requires at least: 3.0.6
6
  Tested up to: 4.2
7
- Stable tag: 1.1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -63,12 +63,26 @@ The API key can also be configured in wp-config.php. You can add a TINY_API_KEY
63
  == Screenshots ==
64
 
65
  1. Enter your TinyPNG or TinyJPG API key and configure the image sizes you would like to have compressed.
66
- 2. See how much space TinyPNG has saved you from the media browser!
67
  3. Bulk compress existing images after installing the plugin or when additional sizes have to be compressed.
68
- 4. Compress individual images in case additional sizes have to be compressed.
 
69
 
70
  == Changelog ==
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  = 1.1.0 =
73
  * The API key can now be set with the TINY_API_KEY constant in wp-config.php. This will work for normal and multisite WordPress installations.
74
  * You can now enable or disable compression of the original uploaded image. If you upgrade the plugin from version 1.0 you may need to go to media settings to include it for compression.
4
  Tags: compress, optimize, shrink, improve, images, tinypng, tinyjpg, jpeg, jpg, png, lossy, jpegmini, crunch, minify, smush, save, bandwidth, website, speed, faster, performance, panda
5
  Requires at least: 3.0.6
6
  Tested up to: 4.2
7
+ Stable tag: 1.3.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
63
  == Screenshots ==
64
 
65
  1. Enter your TinyPNG or TinyJPG API key and configure the image sizes you would like to have compressed.
66
+ 2. See how much space TinyPNG has saved you from the media browser and compress additional sizes per image.
67
  3. Bulk compress existing images after installing the plugin or when additional sizes have to be compressed.
68
+ 4. Show progress while bulk compressing (selection from) media library.
69
+ 5. Bulk compress complete media library.
70
 
71
  == Changelog ==
72
 
73
+ = 1.3.0 =
74
+ * Improved bulk compressions from media library. You can now also bulk compress your whole media library in one step.
75
+ * Intelligent detection if file is already compressed or was altered by another plugin and should be recompressed.
76
+
77
+ = 1.2.1 =
78
+ * Bugfix that prevents recompressing the original when no additional image sizes can be found in the metadata. (introduced in 1.2.0)
79
+
80
+ = 1.2.0 =
81
+ * Display connection status and number of compressions this month on the settings page. This also allows you to check if you entered a valid API key.
82
+ * Show a notice to administrators when reaching the monthly compression limit (in case you're on a fixed or free plan).
83
+ * The plugin will now work when php's parse_ini_file is disabled on your host.
84
+ * Bugfix that avoids a warning when no additional image sizes can be found in the metadata.
85
+
86
  = 1.1.0 =
87
  * The API key can now be set with the TINY_API_KEY constant in wp-config.php. This will work for normal and multisite WordPress installations.
88
  * You can now enable or disable compression of the original uploaded image. If you upgrade the plugin from version 1.0 you may need to go to media settings to include it for compression.
src/cacert.pem CHANGED
@@ -1,7 +1,7 @@
1
  ##
2
  ## Bundle of CA Root Certificates
3
  ##
4
- ## Certificate data from Mozilla downloaded on: Wed Sep 3 03:12:03 2014
5
  ##
6
  ## This is a bundle of X.509 certificates of public Certificate Authorities
7
  ## (CA). These were automatically extracted from Mozilla's root certificates
@@ -13,66 +13,11 @@
13
  ## an Apache+mod_ssl webserver for SSL client authentication.
14
  ## Just configure this file as the SSLCACertificateFile.
15
  ##
16
- ## Conversion done with mk-ca-bundle.pl verison 1.22.
17
- ## SHA1: c4540021427a6fa29e5f50db9f12d48c97d33889
18
  ##
19
 
20
 
21
- GTE CyberTrust Global Root
22
- ==========================
23
- -----BEGIN CERTIFICATE-----
24
- MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
25
- Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
26
- A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
27
- MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
28
- Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
29
- IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
30
- sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
31
- HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
32
- AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
33
- M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
34
- NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
35
- -----END CERTIFICATE-----
36
-
37
- Thawte Server CA
38
- ================
39
- -----BEGIN CERTIFICATE-----
40
- MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
41
- DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
42
- dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
43
- AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
44
- b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
45
- BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
46
- c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
47
- A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
48
- ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
49
- /Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
50
- 1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
51
- MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
52
- GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
53
- GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
54
- -----END CERTIFICATE-----
55
-
56
- Thawte Premium Server CA
57
- ========================
58
- -----BEGIN CERTIFICATE-----
59
- MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
60
- DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
61
- dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
62
- AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
63
- ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
64
- AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
65
- VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
66
- aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
67
- cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
68
- aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
69
- Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
70
- qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
71
- SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
72
- 8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
73
- UCemDaYj+bvLpgcUQg==
74
- -----END CERTIFICATE-----
75
-
76
  Equifax Secure CA
77
  =================
78
  -----BEGIN CERTIFICATE-----
@@ -93,25 +38,6 @@ BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
93
  70+sB3c4
94
  -----END CERTIFICATE-----
95
 
96
- Verisign Class 3 Public Primary Certification Authority - G2
97
- ============================================================
98
- -----BEGIN CERTIFICATE-----
99
- MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
100
- MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
101
- eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
102
- biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
103
- dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
104
- MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
105
- eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
106
- biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
107
- dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO
108
- FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71
109
- lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB
110
- MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT
111
- 1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD
112
- Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9
113
- -----END CERTIFICATE-----
114
-
115
  GlobalSign Root CA
116
  ==================
117
  -----BEGIN CERTIFICATE-----
@@ -248,40 +174,6 @@ Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
248
  RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
249
  -----END CERTIFICATE-----
250
 
251
- Equifax Secure Global eBusiness CA
252
- ==================================
253
- -----BEGIN CERTIFICATE-----
254
- MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
255
- RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp
256
- bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx
257
- HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds
258
- b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV
259
- PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN
260
- qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn
261
- hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
262
- BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs
263
- MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN
264
- I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY
265
- NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
266
- -----END CERTIFICATE-----
267
-
268
- Equifax Secure eBusiness CA 1
269
- =============================
270
- -----BEGIN CERTIFICATE-----
271
- MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
272
- RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB
273
- LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE
274
- ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz
275
- IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ
276
- 1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a
277
- IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk
278
- MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW
279
- Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF
280
- AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5
281
- lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+
282
- KpYrtWKmpj29f5JZzVoqgrI3eQ==
283
- -----END CERTIFICATE-----
284
-
285
  AddTrust Low-Value Services Root
286
  ================================
287
  -----BEGIN CERTIFICATE-----
@@ -527,59 +419,6 @@ gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
527
  X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
528
  -----END CERTIFICATE-----
529
 
530
- America Online Root Certification Authority 1
531
- =============================================
532
- -----BEGIN CERTIFICATE-----
533
- MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
534
- QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
535
- Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG
536
- A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
537
- T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD
538
- ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG
539
- v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z
540
- DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh
541
- sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP
542
- 8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T
543
- AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z
544
- o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf
545
- GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF
546
- VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft
547
- 3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g
548
- Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
549
- sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
550
- -----END CERTIFICATE-----
551
-
552
- America Online Root Certification Authority 2
553
- =============================================
554
- -----BEGIN CERTIFICATE-----
555
- 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
- QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
557
- 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
- A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
559
- 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
- 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
- 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
- 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
- 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
- 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
- gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn
566
- 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
- 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
- Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj
569
- 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
- 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
- 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
- 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
- +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
- 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
- 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
- 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
- 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
- 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
- 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
580
- cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=
581
- -----END CERTIFICATE-----
582
-
583
  Visa eCommerce Root
584
  ===================
585
  -----BEGIN CERTIFICATE-----
@@ -1777,33 +1616,6 @@ JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk
1777
  vQ==
1778
  -----END CERTIFICATE-----
1779
 
1780
- TC TrustCenter Class 3 CA II
1781
- ============================
1782
- -----BEGIN CERTIFICATE-----
1783
- MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
1784
- REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
1785
- IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw
1786
- MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
1787
- c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE
1788
- AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
1789
- AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W
1790
- yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo
1791
- 6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ
1792
- uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk
1793
- 2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB
1794
- /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB
1795
- 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
1796
- Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
1797
- cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
1798
- SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
1799
- TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE
1800
- O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8
1801
- yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9
1802
- IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal
1803
- 092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc
1804
- 5A==
1805
- -----END CERTIFICATE-----
1806
-
1807
  TC TrustCenter Universal CA I
1808
  =============================
1809
  -----BEGIN CERTIFICATE-----
@@ -2421,28 +2233,6 @@ yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
2421
  LXpUq3DDfSJlgnCW
2422
  -----END CERTIFICATE-----
2423
 
2424
- E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
2425
- ===================================================
2426
- -----BEGIN CERTIFICATE-----
2427
- MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
2428
- EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz
2429
- ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3
2430
- MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0
2431
- cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u
2432
- aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
2433
- AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY
2434
- 8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y
2435
- jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI
2436
- JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk
2437
- 9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
2438
- AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG
2439
- SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d
2440
- F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq
2441
- D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4
2442
- Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
2443
- fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
2444
- -----END CERTIFICATE-----
2445
-
2446
  GlobalSign Root CA - R3
2447
  =======================
2448
  -----BEGIN CERTIFICATE-----
@@ -3892,3 +3682,307 @@ ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
3892
  T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
3893
  kI26oQ==
3894
  -----END CERTIFICATE-----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ##
2
  ## Bundle of CA Root Certificates
3
  ##
4
+ ## Certificate data from Mozilla as of: Wed Apr 22 03:12:04 2015
5
  ##
6
  ## This is a bundle of X.509 certificates of public Certificate Authorities
7
  ## (CA). These were automatically extracted from Mozilla's root certificates
13
  ## an Apache+mod_ssl webserver for SSL client authentication.
14
  ## Just configure this file as the SSLCACertificateFile.
15
  ##
16
+ ## Conversion done with mk-ca-bundle.pl version 1.25.
17
+ ## SHA1: ed3c0bbfb7912bcc00cd2033b0cb85c98d10559c
18
  ##
19
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  Equifax Secure CA
22
  =================
23
  -----BEGIN CERTIFICATE-----
38
  70+sB3c4
39
  -----END CERTIFICATE-----
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  GlobalSign Root CA
42
  ==================
43
  -----BEGIN CERTIFICATE-----
174
  RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
175
  -----END CERTIFICATE-----
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  AddTrust Low-Value Services Root
178
  ================================
179
  -----BEGIN CERTIFICATE-----
419
  X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
420
  -----END CERTIFICATE-----
421
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
422
  Visa eCommerce Root
423
  ===================
424
  -----BEGIN CERTIFICATE-----
1616
  vQ==
1617
  -----END CERTIFICATE-----
1618
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1619
  TC TrustCenter Universal CA I
1620
  =============================
1621
  -----BEGIN CERTIFICATE-----
2233
  LXpUq3DDfSJlgnCW
2234
  -----END CERTIFICATE-----
2235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2236
  GlobalSign Root CA - R3
2237
  =======================
2238
  -----BEGIN CERTIFICATE-----
3682
  T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
3683
  kI26oQ==
3684
  -----END CERTIFICATE-----
3685
+
3686
+ COMODO RSA Certification Authority
3687
+ ==================================
3688
+ -----BEGIN CERTIFICATE-----
3689
+ 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
3715
+ LaZRfyHBNVOFBkpdn627G190
3716
+ -----END CERTIFICATE-----
3717
+
3718
+ USERTrust RSA Certification Authority
3719
+ =====================================
3720
+ -----BEGIN CERTIFICATE-----
3721
+ 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
3747
+ Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
3748
+ -----END CERTIFICATE-----
3749
+
3750
+ USERTrust ECC Certification Authority
3751
+ =====================================
3752
+ -----BEGIN CERTIFICATE-----
3753
+ MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
3754
+ VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
3755
+ aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
3756
+ biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
3757
+ VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
3758
+ aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
3759
+ biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
3760
+ 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
3761
+ nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
3762
+ HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
3763
+ HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
3764
+ 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
3765
+ -----END CERTIFICATE-----
3766
+
3767
+ GlobalSign ECC Root CA - R4
3768
+ ===========================
3769
+ -----BEGIN CERTIFICATE-----
3770
+ MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
3771
+ R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
3772
+ EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
3773
+ R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
3774
+ EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
3775
+ OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
3776
+ AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
3777
+ MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
3778
+ JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
3779
+ -----END CERTIFICATE-----
3780
+
3781
+ GlobalSign ECC Root CA - R5
3782
+ ===========================
3783
+ -----BEGIN CERTIFICATE-----
3784
+ MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
3785
+ R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
3786
+ EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
3787
+ R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
3788
+ EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
3789
+ SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
3790
+ h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
3791
+ BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
3792
+ uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
3793
+ yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
3794
+ -----END CERTIFICATE-----
3795
+
3796
+ Staat der Nederlanden Root CA - G3
3797
+ ==================================
3798
+ -----BEGIN CERTIFICATE-----
3799
+ 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
3824
+ -----END CERTIFICATE-----
3825
+
3826
+ Staat der Nederlanden EV Root CA
3827
+ ================================
3828
+ -----BEGIN CERTIFICATE-----
3829
+ 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
3853
+ eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
3854
+ -----END CERTIFICATE-----
3855
+
3856
+ IdenTrust Commercial Root CA 1
3857
+ ==============================
3858
+ -----BEGIN CERTIFICATE-----
3859
+ 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
3883
+ cGzM7vRX+Bi6hG6H
3884
+ -----END CERTIFICATE-----
3885
+
3886
+ IdenTrust Public Sector Root CA 1
3887
+ =================================
3888
+ -----BEGIN CERTIFICATE-----
3889
+ MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
3890
+ EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
3891
+ ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
3892
+ UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
3893
+ b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
3894
+ P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
3895
+ Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
3896
+ rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
3897
+ qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
3898
+ mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
3899
+ ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
3900
+ LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
3901
+ iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
3902
+ 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
3903
+ Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
3904
+ DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
3905
+ t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
3906
+ mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
3907
+ GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
3908
+ m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
3909
+ NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
3910
+ Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
3911
+ ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
3912
+ ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
3913
+ 3Wl9af0AVqW3rLatt8o+Ae+c
3914
+ -----END CERTIFICATE-----
3915
+
3916
+ Entrust Root Certification Authority - G2
3917
+ =========================================
3918
+ -----BEGIN CERTIFICATE-----
3919
+ MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
3920
+ BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
3921
+ bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
3922
+ b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
3923
+ HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
3924
+ DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
3925
+ OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
3926
+ eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
3927
+ MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
3928
+ /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
3929
+ HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
3930
+ s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
3931
+ TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
3932
+ AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
3933
+ 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
3934
+ iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
3935
+ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
3936
+ nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
3937
+ vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
3938
+ e4pIb4tF9g==
3939
+ -----END CERTIFICATE-----
3940
+
3941
+ Entrust Root Certification Authority - EC1
3942
+ ==========================================
3943
+ -----BEGIN CERTIFICATE-----
3944
+ MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
3945
+ FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
3946
+ YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
3947
+ ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
3948
+ IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
3949
+ FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
3950
+ LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
3951
+ dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
3952
+ IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
3953
+ AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
3954
+ 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
3955
+ FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
3956
+ vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
3957
+ kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
3958
+ -----END CERTIFICATE-----
3959
+
3960
+ CFCA EV ROOT
3961
+ ============
3962
+ -----BEGIN CERTIFICATE-----
3963
+ MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
3964
+ CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
3965
+ IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
3966
+ MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
3967
+ DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
3968
+ BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
3969
+ 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
3970
+ uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
3971
+ ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
3972
+ xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
3973
+ py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
3974
+ gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
3975
+ hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
3976
+ tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
3977
+ BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
3978
+ /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
3979
+ ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
3980
+ ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
3981
+ 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
3982
+ E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
3983
+ BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
3984
+ aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
3985
+ PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
3986
+ kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
3987
+ ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
3988
+ -----END CERTIFICATE-----
src/class-tiny-compress-curl.php CHANGED
@@ -20,8 +20,8 @@
20
 
21
  class Tiny_Compress_Curl extends Tiny_Compress {
22
  protected function shrink_options($input) {
23
- return array(
24
- CURLOPT_URL => $this->config['api']['url'],
25
  CURLOPT_USERPWD => 'api:' . $this->api_key,
26
  CURLOPT_POSTFIELDS => $input,
27
  CURLOPT_BINARYTRANSFER => true,
@@ -31,6 +31,14 @@ class Tiny_Compress_Curl extends Tiny_Compress {
31
  CURLOPT_SSL_VERIFYPEER => true,
32
  CURLOPT_USERAGENT => Tiny_WP_Base::plugin_identification() . ' cURL'
33
  );
 
 
 
 
 
 
 
 
34
  }
35
 
36
  protected function shrink($input) {
@@ -42,18 +50,16 @@ class Tiny_Compress_Curl extends Tiny_Compress {
42
  if ($response === false) {
43
  return array(array(
44
  'error' => 'CurlError',
45
- 'message' => curl_error($request)
46
  ), null
47
  );
48
  }
49
 
50
  $header_size = curl_getinfo($request, CURLINFO_HEADER_SIZE);
51
- if (curl_getinfo($request, CURLINFO_HTTP_CODE) === 201) {
52
- $output_url = self::parse_location_header(substr($response, 0, $header_size));
53
- }
54
  curl_close($request);
55
 
56
- return array(self::decode(substr($response, $header_size)), $output_url);
57
  }
58
 
59
  protected function output_options($url) {
20
 
21
  class Tiny_Compress_Curl extends Tiny_Compress {
22
  protected function shrink_options($input) {
23
+ $options = array(
24
+ CURLOPT_URL => Tiny_Config::URL,
25
  CURLOPT_USERPWD => 'api:' . $this->api_key,
26
  CURLOPT_POSTFIELDS => $input,
27
  CURLOPT_BINARYTRANSFER => true,
31
  CURLOPT_SSL_VERIFYPEER => true,
32
  CURLOPT_USERAGENT => Tiny_WP_Base::plugin_identification() . ' cURL'
33
  );
34
+ if (TINY_DEBUG) {
35
+ $f = fopen(dirname(__FILE__) . '/curl.log', 'w');
36
+ if (is_resource($f)) {
37
+ $options[CURLOPT_VERBOSE] = true;
38
+ $options[CURLOPT_STDERR] = $f;
39
+ }
40
+ }
41
+ return $options;
42
  }
43
 
44
  protected function shrink($input) {
50
  if ($response === false) {
51
  return array(array(
52
  'error' => 'CurlError',
53
+ 'message' => sprintf("%s [%d]", curl_error($request), curl_errno($request))
54
  ), null
55
  );
56
  }
57
 
58
  $header_size = curl_getinfo($request, CURLINFO_HEADER_SIZE);
59
+ $headers = self::parse_headers(substr($response, 0, $header_size));
 
 
60
  curl_close($request);
61
 
62
+ return array(self::decode(substr($response, $header_size)), $headers);
63
  }
64
 
65
  protected function output_options($url) {
src/class-tiny-compress-fopen.php CHANGED
@@ -39,7 +39,7 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
39
 
40
  protected function shrink($input) {
41
  $context = stream_context_create($this->shrink_options($input));
42
- $request = @fopen($this->config['api']['url'], 'r', false, $context);
43
 
44
  if (!$request) {
45
  return array(array(
@@ -51,10 +51,10 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
51
 
52
  $response = stream_get_contents($request);
53
  $meta_data = stream_get_meta_data($request);
54
- $output_url = self::parse_location_header($meta_data['wrapper_data']);
55
  fclose($request);
56
 
57
- return array(self::decode($response), $output_url);
58
  }
59
 
60
  protected function output_options() {
@@ -82,4 +82,8 @@ class Tiny_Compress_Fopen extends Tiny_Compress {
82
 
83
  return $response;
84
  }
 
 
 
 
85
  }
39
 
40
  protected function shrink($input) {
41
  $context = stream_context_create($this->shrink_options($input));
42
+ $request = @fopen(Tiny_Config::URL, 'r', false, $context);
43
 
44
  if (!$request) {
45
  return array(array(
51
 
52
  $response = stream_get_contents($request);
53
  $meta_data = stream_get_meta_data($request);
54
+ $headers = self::parse_headers($meta_data['wrapper_data']);
55
  fclose($request);
56
 
57
+ return array(self::decode($response), $headers);
58
  }
59
 
60
  protected function output_options() {
82
 
83
  return $response;
84
  }
85
+
86
+ public function get_status(&$details) {
87
+ return null;
88
+ }
89
  }
src/class-tiny-compress.php CHANGED
@@ -20,35 +20,44 @@
20
 
21
  abstract class Tiny_Compress {
22
  protected $api_key;
23
- protected $config;
24
 
25
  public static function get_ca_file() {
26
  return dirname(__FILE__) . '/cacert.pem';
27
  }
28
 
29
- public static function get_config() {
30
- return parse_ini_file(dirname(__FILE__) . '/config/tinypng-api.ini', true);
31
- }
32
-
33
- public static function get_compressor($api_key) {
34
  if (Tiny_PHP::is_curl_available()) {
35
- return new Tiny_Compress_Curl($api_key, self::get_config());
36
  } elseif (Tiny_PHP::is_fopen_available()) {
37
- return new Tiny_Compress_Fopen($api_key, self::get_config());
38
  }
39
  throw new Tiny_Exception('No HTTP client is available (cURL or fopen)', 'NoHttpClient');
40
  }
41
 
42
- protected function __construct($api_key, $config) {
43
  $this->api_key = $api_key;
44
- $this->config = $config;
45
  }
46
 
47
  abstract protected function shrink($input);
48
  abstract protected function output($url);
49
 
 
 
 
 
 
 
 
 
 
 
 
50
  public function compress($input) {
51
- list($details, $outputUrl) = $this->shrink($input);
 
 
52
  if (isset($details['error']) && $details['error']) {
53
  throw new Tiny_Exception($details['message'], $details['error']);
54
  } else if ($outputUrl === null) {
@@ -70,16 +79,24 @@ abstract class Tiny_Compress {
70
  return $details;
71
  }
72
 
73
- protected static function parse_location_header($headers) {
 
 
 
 
 
 
74
  if (!is_array($headers)) {
75
  $headers = explode("\r\n", $headers);
76
  }
 
77
  foreach ($headers as $header) {
78
- if (substr($header, 0, 10) === "Location: ") {
79
- return substr($header, 10);
 
80
  }
81
  }
82
- return null;
83
  }
84
 
85
  protected static function decode($text) {
20
 
21
  abstract class Tiny_Compress {
22
  protected $api_key;
23
+ protected $after_compress_callback;
24
 
25
  public static function get_ca_file() {
26
  return dirname(__FILE__) . '/cacert.pem';
27
  }
28
 
29
+ public static function get_compressor($api_key, $after_compress_callback=null) {
 
 
 
 
30
  if (Tiny_PHP::is_curl_available()) {
31
+ return new Tiny_Compress_Curl($api_key, $after_compress_callback);
32
  } elseif (Tiny_PHP::is_fopen_available()) {
33
+ return new Tiny_Compress_Fopen($api_key, $after_compress_callback);
34
  }
35
  throw new Tiny_Exception('No HTTP client is available (cURL or fopen)', 'NoHttpClient');
36
  }
37
 
38
+ protected function __construct($api_key, $after_compress_callback) {
39
  $this->api_key = $api_key;
40
+ $this->after_compress_callback = $after_compress_callback;
41
  }
42
 
43
  abstract protected function shrink($input);
44
  abstract protected function output($url);
45
 
46
+ public function get_status(&$details) {
47
+ list($details, $headers) = $this->shrink(null);
48
+
49
+ $this->call_after_compress_callback($details, $headers);
50
+ if (!isset($details['error']) || $details["error"] == 'InputMissing' || $details["error"] == 'TooManyRequests') {
51
+ return true;
52
+ } else {
53
+ return false;
54
+ }
55
+ }
56
+
57
  public function compress($input) {
58
+ list($details, $headers) = $this->shrink($input);
59
+ $this->call_after_compress_callback($details, $headers);
60
+ $outputUrl = isset($headers['location']) ? $headers['location'] : null;
61
  if (isset($details['error']) && $details['error']) {
62
  throw new Tiny_Exception($details['message'], $details['error']);
63
  } else if ($outputUrl === null) {
79
  return $details;
80
  }
81
 
82
+ protected function call_after_compress_callback($details, $headers) {
83
+ if ($this->after_compress_callback) {
84
+ call_user_func($this->after_compress_callback, $details, $headers);
85
+ }
86
+ }
87
+
88
+ protected static function parse_headers($headers) {
89
  if (!is_array($headers)) {
90
  $headers = explode("\r\n", $headers);
91
  }
92
+ $res = array();
93
  foreach ($headers as $header) {
94
+ $split = explode(":", $header, 2);
95
+ if (count($split) === 2) {
96
+ $res[strtolower($split[0])] = trim($split[1]);
97
  }
98
  }
99
+ return $res;
100
  }
101
 
102
  protected static function decode($text) {
src/class-tiny-metadata.php CHANGED
@@ -24,15 +24,48 @@ class Tiny_Metadata {
24
 
25
  private $id;
26
  private $values;
 
 
27
 
28
- public function __construct($id) {
29
  $this->id = $id;
 
 
 
 
 
30
  $this->values = get_post_meta($id, self::META_KEY, true);
31
  if (!is_array($this->values)) {
32
  $this->values = array();
33
  }
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  public function update() {
37
  update_post_meta($this->id, self::META_KEY, $this->values);
38
  }
@@ -53,16 +86,39 @@ class Tiny_Metadata {
53
  );
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  public function get_value($size=self::ORIGINAL) {
57
  return isset($this->values[$size]) ? $this->values[$size] : null;
58
  }
59
 
60
  public function is_compressed($size=self::ORIGINAL) {
61
- return isset($this->values[$size]) && isset($this->values[$size]['output']);
 
 
 
 
 
 
 
 
 
 
62
  }
63
 
64
- public function get_missing_sizes($sizes) {
65
- return array_diff($sizes, array_filter(array_keys($this->values), array($this, 'is_compressed')));
 
66
  }
67
 
68
  public function get_latest_error() {
24
 
25
  private $id;
26
  private $values;
27
+ private $filenames;
28
+ private $urls;
29
 
30
+ public function __construct($id, $wp_metadata=null) {
31
  $this->id = $id;
32
+
33
+ if (is_null($wp_metadata)) {
34
+ $wp_metadata = wp_get_attachment_metadata($id);
35
+ }
36
+ $this->parse_wp_metadata($wp_metadata);
37
  $this->values = get_post_meta($id, self::META_KEY, true);
38
  if (!is_array($this->values)) {
39
  $this->values = array();
40
  }
41
  }
42
 
43
+ private function parse_wp_metadata($wp_metadata) {
44
+ $this->filenames = array();
45
+ $this->urls = array();
46
+ if (!is_array($wp_metadata)) {
47
+ return;
48
+ }
49
+
50
+ $path_info = pathinfo($wp_metadata['file']);
51
+ $upload_dir = wp_upload_dir();
52
+ $path_prefix = $upload_dir['basedir'] . '/';
53
+ $url_prefix = $upload_dir['baseurl'] . '/';
54
+ if (isset($path_info['dirname'])) {
55
+ $path_prefix .= $path_info['dirname'] .'/';
56
+ $url_prefix .= $path_info['dirname'] .'/';
57
+ }
58
+
59
+ $this->filenames[self::ORIGINAL] = "$path_prefix${path_info['basename']}";
60
+ $this->urls[self::ORIGINAL] = "$url_prefix${path_info['basename']}";
61
+ if (isset($wp_metadata['sizes']) && is_array($wp_metadata['sizes'])) {
62
+ foreach ($wp_metadata['sizes'] as $size => $info) {
63
+ $this->filenames[$size] = "$path_prefix${info['file']}";
64
+ $this->urls[$size] = "$url_prefix${info['file']}";
65
+ }
66
+ }
67
+ }
68
+
69
  public function update() {
70
  update_post_meta($this->id, self::META_KEY, $this->values);
71
  }
86
  );
87
  }
88
 
89
+ public function get_id() {
90
+ return $this->id;
91
+ }
92
+
93
+ public function get_filename($size=self::ORIGINAL) {
94
+ return isset($this->filenames[$size]) ? $this->filenames[$size] : null;
95
+ }
96
+
97
+ public function get_url($size=self::ORIGINAL) {
98
+ return isset($this->urls[$size]) ? $this->urls[$size] : null;
99
+ }
100
+
101
  public function get_value($size=self::ORIGINAL) {
102
  return isset($this->values[$size]) ? $this->values[$size] : null;
103
  }
104
 
105
  public function is_compressed($size=self::ORIGINAL) {
106
+ $filename = $this->get_filename($size);
107
+ return isset($this->values[$size]) && isset($this->values[$size]['output'])
108
+ && file_exists($filename) && filesize($filename) == $this->values[$size]['output']['size'];
109
+ }
110
+
111
+ public function get_sizes() {
112
+ return array_keys($this->filenames);
113
+ }
114
+
115
+ public function get_success_sizes() {
116
+ return array_filter(array_keys($this->values), array($this, 'is_compressed'));
117
  }
118
 
119
+ public function get_missing_sizes($tinify_sizes) {
120
+ $sizes = array_intersect($this->get_sizes(), $tinify_sizes);
121
+ return array_diff($sizes, $this->get_success_sizes());
122
  }
123
 
124
  public function get_latest_error() {
src/class-tiny-notices.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Tiny Compress Images - WordPress plugin.
4
+ * Copyright (C) 2015 Voormedia B.V.
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify it
7
+ * under the terms of the GNU General Public License as published by the Free
8
+ * Software Foundation; either version 2 of the License, or (at your option)
9
+ * any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
+ * more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along
17
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
18
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ */
20
+
21
+ class Tiny_Notices extends Tiny_WP_Base {
22
+
23
+ private $notices;
24
+ private $dismissals;
25
+
26
+ private static function get_option_key() {
27
+ return self::get_prefixed_name('admin_notices');
28
+ }
29
+
30
+ private static function get_user_meta_key() {
31
+ return self::get_prefixed_name('admin_notice_dismissals');
32
+ }
33
+
34
+ public function admin_init() {
35
+ add_action('wp_ajax_tiny_dismiss_notice', $this->get_method('dismiss'));
36
+ if (current_user_can('manage_options')) {
37
+ $this->show_stored();
38
+ }
39
+ }
40
+
41
+ private function load_notices() {
42
+ if (is_array($this->notices)) {
43
+ return;
44
+ }
45
+ $option = get_option(self::get_option_key());
46
+ $this->notices = is_array($option) ? $option : array();
47
+ }
48
+
49
+ private function save_notices() {
50
+ update_option(self::get_option_key(), $this->notices);
51
+ }
52
+
53
+ private function load() {
54
+ $this->load_notices();
55
+ $this->load_dismissals();
56
+ }
57
+
58
+ private function load_dismissals() {
59
+ if (is_array($this->dismissals)) {
60
+ return;
61
+ }
62
+ $meta = get_user_meta($this->get_user_id(), $this->get_user_meta_key(), true);
63
+ $this->dismissals = is_array($meta) ? $meta : array();
64
+ }
65
+
66
+ private function save_dismissals() {
67
+ update_user_meta($this->get_user_id(), $this->get_user_meta_key(), $this->dismissals);
68
+ }
69
+
70
+ private function show_stored() {
71
+ $this->load();
72
+ foreach ($this->notices as $name => $message) {
73
+ if (empty($this->dismissals[$name])) {
74
+ $this->show($name, $message);
75
+ }
76
+ }
77
+ }
78
+
79
+ public function add($name, $message) {
80
+ $this->load_notices();
81
+ $this->notices[$name] = $message;
82
+ $this->save_notices();
83
+ }
84
+
85
+ public function remove($name) {
86
+ $this->load();
87
+ if (isset($this->notices[$name])) {
88
+ unset($this->notices[$name]);
89
+ $this->save_notices();
90
+ }
91
+ if (isset($this->dismissals[$name])) {
92
+ unset($this->dismissals[$name]);
93
+ $this->save_dismissals();
94
+ }
95
+ }
96
+
97
+ public function dismiss() {
98
+ if (empty($_POST['name']) || !$this->check_ajax_referer()) {
99
+ echo json_encode(false);
100
+ exit();
101
+ }
102
+ $this->load_dismissals();
103
+ $this->dismissals[$_POST['name']] = true;
104
+ $this->save_dismissals();
105
+ echo json_encode(true);
106
+ exit();
107
+ }
108
+
109
+ public function show($name, $message, $klass='error', $dismissible=true) {
110
+ $css = array($klass, 'notice', 'tiny-notice');
111
+ if (!$dismissible) {
112
+ $add = '</p>';
113
+ } else if (self::check_wp_version(4.2)) {
114
+ $add = '</p>';
115
+ $css[] = 'is-dismissible';
116
+ } else {
117
+ $add = '&nbsp;<a href="#" class="tiny-dismiss">' . self::translate_escape('Dismiss') . '</a></p>';
118
+ }
119
+ $css = implode(' ', $css);
120
+ add_action('admin_notices', create_function('', "echo '<div class=\"$css\" data-name=\"$name\"><p>Compress JPEG & PNG images: $message$add</div>';"));
121
+ }
122
+ }
src/class-tiny-plugin.php CHANGED
@@ -23,7 +23,6 @@ class Tiny_Plugin extends Tiny_WP_Base {
23
  const MEDIA_COLUMN_HEADER = 'Compression';
24
 
25
  private $settings;
26
- private $compressor;
27
 
28
  public static function jpeg_quality() {
29
  return 95;
@@ -32,15 +31,13 @@ class Tiny_Plugin extends Tiny_WP_Base {
32
  public function __construct() {
33
  parent::__construct();
34
  $this->settings = new Tiny_Settings();
35
- try {
36
- $this->compressor = Tiny_Compress::get_compressor($this->settings->get_api_key());
37
- } catch (Tiny_Exception $e) {
38
- $this->add_admin_notice(self::translate_escape($e->getMessage()));
39
  }
40
  }
41
 
42
  public function set_compressor($compressor) {
43
- $this->compressor = $compressor;
44
  }
45
 
46
  public function init() {
@@ -58,6 +55,14 @@ class Tiny_Plugin extends Tiny_WP_Base {
58
  add_action('admin_enqueue_scripts', $this->get_method('enqueue_scripts'));
59
  }
60
 
 
 
 
 
 
 
 
 
61
  public function enqueue_scripts($hook) {
62
  wp_enqueue_style(self::NAME .'_admin', plugins_url('/styles/admin.css', __FILE__),
63
  array(), self::plugin_version());
@@ -66,67 +71,88 @@ class Tiny_Plugin extends Tiny_WP_Base {
66
  wp_register_script($handle, plugins_url('/scripts/admin.js', __FILE__),
67
  array(), self::plugin_version(), true);
68
 
69
- wp_localize_script($handle, 'tinyCompressL10n', array(
70
- 'bulkAction' => self::translate('Compress all uncompressed sizes'),
 
 
 
 
 
 
 
 
 
 
 
71
  ));
72
  wp_enqueue_script($handle);
73
  }
74
 
75
- public function compress_attachment($metadata, $attachment_id) {
76
  $mime_type = get_post_mime_type($attachment_id);
77
- $tiny_metadata = new Tiny_Metadata($attachment_id);
78
 
79
- if ($this->compressor === null || strpos($mime_type, 'image/') !== 0) {
80
  return $metadata;
81
  }
82
 
83
- $path_info = pathinfo($metadata['file']);
84
- $upload_dir = wp_upload_dir();
85
- $prefix = $upload_dir['basedir'] . '/' . $path_info['dirname'] . '/';
86
-
87
- $settings = $this->settings->get_sizes();
88
 
89
- if ($settings[Tiny_Metadata::ORIGINAL]['tinify'] && !$tiny_metadata->is_compressed()) {
 
 
90
  try {
91
- $response = $this->compressor->compress_file("$prefix${path_info['basename']}");
92
- $tiny_metadata->add_response($response);
 
93
  } catch (Tiny_Exception $e) {
94
- $tiny_metadata->add_exception($e);
95
- }
96
- }
97
-
98
- foreach ($metadata['sizes'] as $size => $info) {
99
- if (isset($settings[$size]) && $settings[$size]['tinify'] && !$tiny_metadata->is_compressed($size)) {
100
- try {
101
- $response = $this->compressor->compress_file("$prefix${info['file']}");
102
- $tiny_metadata->add_response($response, $size);
103
- } catch (Tiny_Exception $e) {
104
- $tiny_metadata->add_exception($e, $size);
105
- }
106
  }
107
  }
108
  $tiny_metadata->update();
109
 
 
 
 
 
 
110
  return $metadata;
111
  }
112
 
113
  public function compress_image() {
114
- $id = $_POST['id'];
 
 
 
115
  if (!current_user_can('upload_files')) {
116
- echo self::translate("You don't have permission to work with uploaded files") . '.';
 
117
  exit();
118
  }
119
- if (!$id) {
120
- echo self::translate("Not a valid media file") . '.';
 
121
  exit();
122
  }
 
123
  $metadata = wp_get_attachment_metadata($id);
124
- if (!$metadata) {
125
- echo self::translate("Could not find metadata of media file") . '.';
 
 
126
  }
127
 
128
- $this->compress_attachment($metadata, $id);
129
- $this->render_media_column(self::MEDIA_COLUMN, $id);
 
 
 
 
 
 
 
130
 
131
  exit();
132
  }
@@ -138,12 +164,13 @@ class Tiny_Plugin extends Tiny_WP_Base {
138
  return;
139
  }
140
 
141
- foreach ($_REQUEST['media'] as $id) {
142
- $metadata = wp_get_attachment_metadata($id);
143
- if ($metadata) {
144
- $this->compress_attachment($metadata, $id);
145
- }
146
- }
 
147
  }
148
 
149
  public function add_media_columns($columns) {
@@ -153,35 +180,83 @@ class Tiny_Plugin extends Tiny_WP_Base {
153
 
154
  public function render_media_column($column, $id) {
155
  if ($column === self::MEDIA_COLUMN) {
156
- $wp_metadata = wp_get_attachment_metadata($id);
157
- $wp_sizes = isset($wp_metadata['sizes']) ? array_keys($wp_metadata['sizes']) : array();
158
- $wp_sizes[] = Tiny_Metadata::ORIGINAL;
159
-
160
- $sizes = array_intersect($wp_sizes, $this->settings->get_tinify_sizes());
161
 
162
- $tiny_metadata = new Tiny_Metadata($id);
163
- $missing = $tiny_metadata->get_missing_sizes($sizes);
164
- $total = count($sizes);
165
- $success = $total - count($missing);
166
 
167
- if (count($missing) > 0) {
168
- printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
 
 
 
 
 
 
 
 
 
 
 
169
  echo '<br/>';
170
- if (($error = $tiny_metadata->get_latest_error())) {
171
- echo '<span class="error">' . self::translate_escape('Latest error') . ': '. self::translate_escape($error) .'<br/>';
172
- }
173
- echo '<button type="button" class="tiny-compress" data-id="' . $id . '">' .
174
- self::translate_escape('Compress') . '</button>';
175
- echo '<div class="spinner"></div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  } else {
177
- printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
178
- $savings = $tiny_metadata->get_savings();
179
- if ($savings['count'] > 0) {
180
- echo '<br/>';
181
- echo self::translate_escape('Total size') . ': ' . size_format($savings['input']) . '<br/>';
182
- echo self::translate_escape('Compressed size') . ': ' . size_format($savings['output']);
183
- }
184
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
 
 
186
  }
187
  }
23
  const MEDIA_COLUMN_HEADER = 'Compression';
24
 
25
  private $settings;
 
26
 
27
  public static function jpeg_quality() {
28
  return 95;
31
  public function __construct() {
32
  parent::__construct();
33
  $this->settings = new Tiny_Settings();
34
+ if (is_admin()) {
35
+ add_action('admin_menu', $this->get_method('admin_menu'));
 
 
36
  }
37
  }
38
 
39
  public function set_compressor($compressor) {
40
+ $this->settings->set_compressor($compressor);
41
  }
42
 
43
  public function init() {
55
  add_action('admin_enqueue_scripts', $this->get_method('enqueue_scripts'));
56
  }
57
 
58
+ public function admin_menu() {
59
+ add_management_page(
60
+ self::translate('Compress JPEG & PNG Images'), self::translate('Compress All Images'),
61
+ 'upload_files', 'tiny-bulk-compress', $this->get_method('bulk_compress_page')
62
+ );
63
+
64
+ }
65
+
66
  public function enqueue_scripts($hook) {
67
  wp_enqueue_style(self::NAME .'_admin', plugins_url('/styles/admin.css', __FILE__),
68
  array(), self::plugin_version());
71
  wp_register_script($handle, plugins_url('/scripts/admin.js', __FILE__),
72
  array(), self::plugin_version(), true);
73
 
74
+ // Wordpress < 3.3 does not handle multi dimensional arrays
75
+ wp_localize_script($handle, 'tinyCompress', array(
76
+ 'nonce' => wp_create_nonce('tiny-compress'),
77
+ 'wpVersion' => self::wp_version(),
78
+ 'pluginVersion' => self::plugin_version(),
79
+ 'L10nAllDone' => self::translate('All images are processed'),
80
+ 'L10nBulkAction' => self::translate('Compress Images'),
81
+ 'L10nCompressing' => self::translate('Compressing'),
82
+ 'L10nCompressions' => self::translate('compressions'),
83
+ 'L10nError' => self::translate('Error'),
84
+ 'L10nInternalError' => self::translate('Internal error'),
85
+ 'L10nOutOf' => self::translate('out of'),
86
+ 'L10nWaiting' => self::translate('Waiting'),
87
  ));
88
  wp_enqueue_script($handle);
89
  }
90
 
91
+ private function compress($metadata, $attachment_id) {
92
  $mime_type = get_post_mime_type($attachment_id);
93
+ $tiny_metadata = new Tiny_Metadata($attachment_id, $metadata);
94
 
95
+ if ($this->settings->get_compressor() === null || strpos($mime_type, 'image/') !== 0) {
96
  return $metadata;
97
  }
98
 
99
+ $success = 0;
100
+ $failed = 0;
 
 
 
101
 
102
+ $compressor = $this->settings->get_compressor();
103
+ $sizes = $this->settings->get_tinify_sizes();
104
+ foreach ($tiny_metadata->get_missing_sizes($sizes) as $size) {
105
  try {
106
+ $response = $compressor->compress_file($tiny_metadata->get_filename($size));
107
+ $tiny_metadata->add_response($response, $size);
108
+ $success++;
109
  } catch (Tiny_Exception $e) {
110
+ $tiny_metadata->add_exception($e, $size);
111
+ $failed++;
 
 
 
 
 
 
 
 
 
 
112
  }
113
  }
114
  $tiny_metadata->update();
115
 
116
+ return array($tiny_metadata, array('success' => $success, 'failed' => $failed));
117
+ }
118
+
119
+ public function compress_attachment($metadata, $attachment_id) {
120
+ $this->compress($metadata, $attachment_id);
121
  return $metadata;
122
  }
123
 
124
  public function compress_image() {
125
+ if (!$this->check_ajax_referer()) {
126
+ exit();
127
+ }
128
+ $json = !empty($_POST['json']) && $_POST['json'];
129
  if (!current_user_can('upload_files')) {
130
+ $message = self::translate("You don't have permission to work with uploaded files") . '.';
131
+ echo $json ? json_encode(array('error' => $message)) : $message;
132
  exit();
133
  }
134
+ if (empty($_POST['id'])) {
135
+ $message = self::translate("Not a valid media file") . '.';
136
+ echo $json ? json_encode(array('error' => $message)) : $message;
137
  exit();
138
  }
139
+ $id = intval($_POST['id']);
140
  $metadata = wp_get_attachment_metadata($id);
141
+ if (!is_array($metadata)) {
142
+ $message = self::translate("Could not find metadata of media file") . '.';
143
+ echo $json ? json_encode(array('error' => $message)) : $message;
144
+ exit;
145
  }
146
 
147
+ list($tiny_metadata, $result) = $this->compress($metadata, $id);
148
+ if ($json) {
149
+ $result['message'] = $tiny_metadata->get_latest_error();
150
+ $result['status'] = $this->settings->get_status();
151
+ $result['thumbnail'] = $tiny_metadata->get_url('thumbnail');
152
+ echo json_encode($result);
153
+ } else {
154
+ echo $this->render_compress_details($tiny_metadata);
155
+ }
156
 
157
  exit();
158
  }
164
  return;
165
  }
166
 
167
+ $ids = implode('-', array_map('intval', $_REQUEST['media']));
168
+ wp_redirect(add_query_arg(
169
+ '_wpnonce',
170
+ wp_create_nonce('tiny-bulk-compress'),
171
+ admin_url("tools.php?page=tiny-bulk-compress&ids=$ids")
172
+ ));
173
+ exit();
174
  }
175
 
176
  public function add_media_columns($columns) {
180
 
181
  public function render_media_column($column, $id) {
182
  if ($column === self::MEDIA_COLUMN) {
183
+ $this->render_compress_details(new Tiny_Metadata($id));
184
+ }
185
+ }
 
 
186
 
187
+ private function render_compress_details($tiny_metadata) {
188
+ $missing = $tiny_metadata->get_missing_sizes($this->settings->get_tinify_sizes());
189
+ $success = count($tiny_metadata->get_success_sizes());
190
+ $total = count($missing) + $success;
191
 
192
+ if (count($missing) > 0) {
193
+ printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
194
+ echo '<br/>';
195
+ if (($error = $tiny_metadata->get_latest_error())) {
196
+ echo '<span class="error">' . self::translate_escape('Latest error') . ': '. self::translate_escape($error) .'</span><br/>';
197
+ }
198
+ echo '<button type="button" class="tiny-compress" data-id="' . $tiny_metadata->get_id() . '">' .
199
+ self::translate_escape('Compress') . '</button>';
200
+ echo '<div class="spinner hidden"></div>';
201
+ } else {
202
+ printf(self::translate_escape('Compressed %d out of %d sizes'), $success, $total);
203
+ $savings = $tiny_metadata->get_savings();
204
+ if ($savings['count'] > 0) {
205
  echo '<br/>';
206
+ echo self::translate_escape('Total size') . ': ' . size_format($savings['input']) . '<br/>';
207
+ echo self::translate_escape('Compressed size') . ': ' . size_format($savings['output']);
208
+ }
209
+ }
210
+ }
211
+
212
+ public function bulk_compress_page() {
213
+ global $wpdb;
214
+
215
+ echo '<div class="wrap" id="tiny-bulk-compress">';
216
+ echo '<h2>' . self::translate('Compress JPEG & PNG Images') . '</h2>';
217
+ if (empty($_POST['tiny-bulk-compress']) && empty($_REQUEST['ids'])) {
218
+ $result = $wpdb->get_results("SELECT COUNT(*) AS `count` FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC", ARRAY_A);
219
+ $count = $result[0]['count'];
220
+
221
+ echo '<p>' . self::translate_escape("Use this tool to compress all images in your media library") . '. ';
222
+ echo self::translate_escape("Only images that have not been compressed will be compressed") . '.</p>';
223
+ echo '<p>' . sprintf(self::translate_escape("We have found %d images in your media library"), $count) . '. ';
224
+ echo self::translate_escape("To begin, just press the button below") . '.</p>';
225
+
226
+ echo '<form method="POST" action="?page=tiny-bulk-compress">';
227
+ echo '<input type="hidden" name="_wpnonce" value="' . wp_create_nonce('tiny-bulk-compress') . '">';
228
+ echo '<input type="hidden" name="tiny-bulk-compress" value="1">';
229
+ echo '<p><button class="button button-primary button-large" type="submit">' .
230
+ self::translate_escape('Compress All Images') . '</p>';
231
+ echo '</form>';
232
+ } else {
233
+ check_admin_referer('tiny-bulk-compress');
234
+
235
+ if (!empty($_REQUEST['ids'])) {
236
+ $ids = implode(',', array_map('intval', explode('-', $_REQUEST['ids'])));
237
+ $cond = "AND ID IN($ids)";
238
  } else {
239
+ $cond = "";
 
 
 
 
 
 
240
  }
241
+
242
+ // Get all ids and names of the images and not the whole objects which will only fill memory
243
+ $items = $wpdb->get_results("SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' $cond ORDER BY ID DESC", ARRAY_A);
244
+
245
+ echo '<p>';
246
+ echo self::translate_escape("Please be patient while the images are being compressed") . '. ';
247
+ echo self::translate_escape("This can take a while if you have many images") . '. ';
248
+ echo self::translate_escape("Do not navigate away from this page because it will stop the process") . '. ';
249
+ echo self::translate_escape("You will be notified via this page when the processing is done") . '.';
250
+ echo "</p>";
251
+
252
+ echo '<div id="tiny-status"><p>'. self::translate_escape('Compressions this month') . sprintf(' <span>%d</span></p></div>', $this->settings->get_status());
253
+ echo '<div id="tiny-progress"><p>'. self::translate_escape('Processing') . ' <span>0</span> ' . self::translate_escape('out of') . sprintf(' %d </p></div>', count($items));
254
+ echo '<div id="media-items">';
255
+ echo '</div>';
256
+
257
+ echo '<script type="text/javascript">jQuery(function() { tinyBulkCompress('. json_encode($items) . ')})</script>';
258
  }
259
+
260
+ echo '</div>';
261
  }
262
  }
src/class-tiny-settings.php CHANGED
@@ -19,17 +19,30 @@
19
  */
20
 
21
  class Tiny_Settings extends Tiny_WP_Base {
22
- const PREFIX = 'tinypng_';
23
  const DUMMY_SIZE = '_tiny_dummy';
24
 
25
- protected static function get_prefixed_name($name) {
26
- return self::PREFIX . $name;
27
- }
28
-
29
  private $sizes;
30
  private $tinify_sizes;
 
 
 
 
 
 
 
31
 
32
  public function admin_init() {
 
 
 
 
 
 
 
 
 
 
 
33
  $section = self::get_prefixed_name('settings');
34
  add_settings_section($section, self::translate('PNG and JPEG compression'), $this->get_method('render_section'), 'media');
35
 
@@ -40,9 +53,32 @@ class Tiny_Settings extends Tiny_WP_Base {
40
  $field = self::get_prefixed_name('sizes');
41
  register_setting('media', $field);
42
  add_settings_field($field, self::translate('File compression'), $this->get_method('render_sizes'), 'media', $section);
 
 
 
 
 
 
43
  }
44
 
45
- public function get_api_key() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  if (defined('TINY_API_KEY')) {
47
  return TINY_API_KEY;
48
  } else {
@@ -113,6 +149,7 @@ class Tiny_Settings extends Tiny_WP_Base {
113
  }
114
 
115
  public function render_section() {
 
116
  }
117
 
118
  public function render_api_key() {
@@ -125,7 +162,7 @@ class Tiny_Settings extends Tiny_WP_Base {
125
  echo '<input type="text" id="' . $field . '" name="' . $field . '" value="' . htmlspecialchars($key) . '" size="40" />';
126
  }
127
  echo '<p>';
128
- $link = '<a href="https://tinypng.com/developers">' . self::translate_escape('TinyPNG Developer section') . '</a>';
129
  if (empty($key)) {
130
  printf(self::translate_escape('Visit %s to get an API key') . '.', $link);
131
  } else {
@@ -156,4 +193,66 @@ class Tiny_Settings extends Tiny_WP_Base {
156
  <label for="<?php echo $id; ?>"><?php echo $label; ?></label></p>
157
  <?php
158
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
19
  */
20
 
21
  class Tiny_Settings extends Tiny_WP_Base {
 
22
  const DUMMY_SIZE = '_tiny_dummy';
23
 
 
 
 
 
24
  private $sizes;
25
  private $tinify_sizes;
26
+ private $compressor;
27
+ private $notices;
28
+
29
+ public function __construct() {
30
+ parent::__construct();
31
+ $this->notices = new Tiny_Notices();
32
+ }
33
 
34
  public function admin_init() {
35
+ if (current_user_can('manage_options') && !$this->get_api_key()) {
36
+ $link = sprintf('<a href="options-media.php#%s">%s</a>', self::NAME,
37
+ self::translate_escape('Please fill in an API key to start compressing images'));
38
+ $this->notices->show('setting', $link, 'error', false);
39
+ }
40
+ try {
41
+ $this->compressor = Tiny_Compress::get_compressor($this->get_api_key(), $this->get_method('after_compress_callback'));
42
+ } catch (Tiny_Exception $e) {
43
+ $this->notices->show('compressor_exception', self::translate_escape($e->getMessage()), 'error', false);
44
+ }
45
+
46
  $section = self::get_prefixed_name('settings');
47
  add_settings_section($section, self::translate('PNG and JPEG compression'), $this->get_method('render_section'), 'media');
48
 
53
  $field = self::get_prefixed_name('sizes');
54
  register_setting('media', $field);
55
  add_settings_field($field, self::translate('File compression'), $this->get_method('render_sizes'), 'media', $section);
56
+
57
+ $field = self::get_prefixed_name('status');
58
+ register_setting('media', $field);
59
+ add_settings_field($field, self::translate('Connection status'), $this->get_method('render_pending_status'), 'media', $section);
60
+
61
+ add_action('wp_ajax_tiny_compress_status', $this->get_method('connection_status'));
62
  }
63
 
64
+ public function connection_status() {
65
+ $this->render_status();
66
+ exit();
67
+ }
68
+
69
+ public function get_compressor() {
70
+ return $this->compressor;
71
+ }
72
+
73
+ public function set_compressor($compressor) {
74
+ $this->compressor = $compressor;
75
+ }
76
+
77
+ public function get_status() {
78
+ return intval(get_option(self::get_prefixed_name('status')));
79
+ }
80
+
81
+ protected function get_api_key() {
82
  if (defined('TINY_API_KEY')) {
83
  return TINY_API_KEY;
84
  } else {
149
  }
150
 
151
  public function render_section() {
152
+ echo '<span id="' . self::NAME . '"></span>';
153
  }
154
 
155
  public function render_api_key() {
162
  echo '<input type="text" id="' . $field . '" name="' . $field . '" value="' . htmlspecialchars($key) . '" size="40" />';
163
  }
164
  echo '<p>';
165
+ $link = '<a href="https://tinypng.com/developers" target="_blank">' . self::translate_escape('TinyPNG Developer section') . '</a>';
166
  if (empty($key)) {
167
  printf(self::translate_escape('Visit %s to get an API key') . '.', $link);
168
  } else {
193
  <label for="<?php echo $id; ?>"><?php echo $label; ?></label></p>
194
  <?php
195
  }
196
+
197
+ public function get_compression_count() {
198
+ $field = self::get_prefixed_name('status');
199
+ return get_option($field);
200
+ }
201
+
202
+ public function after_compress_callback($details, $headers) {
203
+ if (isset($headers['compression-count'])) {
204
+ $count = $headers['compression-count'];
205
+ $field = self::get_prefixed_name('status');
206
+ update_option($field, $count);
207
+
208
+ if (isset($details['error']) && $details['error'] == 'TooManyRequests') {
209
+ $link = '<a href="https://tinypng.com/developers" target="_blank">' . self::translate_escape('TinyPNG API account') . '</a>';
210
+ $this->notices->add('limit-reached',
211
+ sprintf(self::translate_escape('You have reached your limit of %s compressions this month'), $count) . '. ' .
212
+ sprintf(self::translate_escape('Upgrade your %s if you like to compress more images'), $link) . '.');
213
+ } else {
214
+ $this->notices->remove('limit-reached');
215
+ }
216
+ }
217
+ }
218
+
219
+ public function render_status() {
220
+ $details = null;
221
+ try {
222
+ $status = $this->compressor->get_status($details);
223
+ } catch (Tiny_Exception $e) {
224
+ $status = false;
225
+ $details = array('message' => $e->getMessage());
226
+ }
227
+ if ($status) {
228
+ echo '<p><img src="images/yes.png"> ' . self::translate_escape('API connection successful') . '</p>';
229
+ } else {
230
+ if ($status === false) {
231
+ echo '<p><img src="images/no.png"> ' . self::translate_escape('API connection unsuccessful') . '</p>';
232
+ if (isset($details['message'])) {
233
+ echo '<p>'. self::translate_escape('Error') . ': ' . self::translate_escape($details['message']) . '</p>';
234
+ }
235
+ } else {
236
+ echo '<p>' . self::translate_escape('API status could not be checked, enable cURL for more information') . '.</p>';
237
+ }
238
+ return;
239
+ }
240
+
241
+ $compressions = self::get_compression_count();
242
+ echo '<p>';
243
+ // We currently have no way to check if a user is free or flexible.
244
+ if ($compressions == 500) {
245
+ $link = '<a href="https://tinypng.com/developers" target="_blank">' . self::translate_escape('TinyPNG API account') . '</a>';
246
+ printf(self::translate_escape('You have reached your limit of %s compressions this month') . '.', $compressions);
247
+ echo '<br>';
248
+ printf(self::translate_escape('If you need to compress more images you can change your %s') . '.', $link);
249
+ } else {
250
+ printf(self::translate_escape('You have made %s compressions this month') . '.', self::get_compression_count());
251
+ }
252
+ echo '</p>';
253
+ }
254
+
255
+ public function render_pending_status() {
256
+ echo '<div id="tiny-compress-status"><div class="spinner"></div></div>';
257
+ }
258
  }
src/class-tiny-wp-base.php CHANGED
@@ -20,14 +20,42 @@
20
 
21
  abstract class Tiny_WP_Base {
22
  const NAME = 'tiny-compress-images';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  public static function plugin_version() {
25
- $plugin_data = get_plugin_data(dirname(__FILE__) . '/../tiny-compress-images.php');
26
- return $plugin_data['Version'];
 
 
 
27
  }
28
 
29
  public static function plugin_identification() {
30
- return 'Wordpress/' . $GLOBALS['wp_version'] . ' Tiny/' . self::plugin_version();
 
 
 
 
31
  }
32
 
33
  protected static function translate($phrase) {
@@ -40,7 +68,9 @@ abstract class Tiny_WP_Base {
40
 
41
  public function __construct() {
42
  add_action('init', $this->get_method('init'));
43
- add_action('admin_init', $this->get_method('admin_init'));
 
 
44
  }
45
 
46
  protected function get_method($name) {
@@ -51,13 +81,17 @@ abstract class Tiny_WP_Base {
51
  return array(get_class($this), $name);
52
  }
53
 
54
- public function init() {
 
55
  }
56
 
57
- public function admin_init() {
 
 
 
 
58
  }
59
 
60
- public function add_admin_notice($message) {
61
- add_action('admin_notices', create_function('', "echo '<div class=\"error\"><p>Tiny Compress Images: $message</p></div>';"));
62
  }
63
  }
20
 
21
  abstract class Tiny_WP_Base {
22
  const NAME = 'tiny-compress-images';
23
+ const PREFIX = 'tinypng_';
24
+
25
+ private static $wp_version;
26
+ private static $plugin_version;
27
+
28
+ public static function wp_version() {
29
+ if (is_null(self::$wp_version)) {
30
+ // Try to use unmodified version
31
+ include( ABSPATH . WPINC . '/version.php' );
32
+ if (isset($wp_version)) {
33
+ self::$wp_version = $wp_version;
34
+ } else {
35
+ self::$wp_version = $GLOBALS['wp_version'];
36
+ }
37
+ }
38
+ return self::$wp_version;
39
+ }
40
+
41
+ public static function check_wp_version($version) {
42
+ return floatval(self::wp_version()) >= $version;
43
+ }
44
 
45
  public static function plugin_version() {
46
+ if (is_null(self::$plugin_version)) {
47
+ $plugin_data = get_plugin_data(dirname(__FILE__) . '/../tiny-compress-images.php');
48
+ self::$plugin_version = $plugin_data['Version'];
49
+ }
50
+ return self::$plugin_version;
51
  }
52
 
53
  public static function plugin_identification() {
54
+ return 'Wordpress/' . self::wp_version() . ' Tiny/' . self::plugin_version();
55
+ }
56
+
57
+ protected static function get_prefixed_name($name) {
58
+ return self::PREFIX . $name;
59
  }
60
 
61
  protected static function translate($phrase) {
68
 
69
  public function __construct() {
70
  add_action('init', $this->get_method('init'));
71
+ if (is_admin()) {
72
+ add_action('admin_init', $this->get_method('admin_init'));
73
+ }
74
  }
75
 
76
  protected function get_method($name) {
81
  return array(get_class($this), $name);
82
  }
83
 
84
+ protected function get_user_id() {
85
+ return get_current_user_id();
86
  }
87
 
88
+ protected function check_ajax_referer() {
89
+ return check_ajax_referer('tiny-compress', '_nonce', false);
90
+ }
91
+
92
+ public function init() {
93
  }
94
 
95
+ public function admin_init() {
 
96
  }
97
  }
src/config/tiny-config.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class Tiny_Config {
4
+ const URL = 'https://api.tinify.com/shrink';
5
+ }
src/config/tinypng-api.ini DELETED
@@ -1,2 +0,0 @@
1
- [api]
2
- url = "https://api.tinypng.com/shrink"
 
 
src/languages/tiny-compress-images-nl_NL.mo CHANGED
Binary file
src/languages/tiny-compress-images-nl_NL.po CHANGED
@@ -37,8 +37,8 @@ msgstr "Compressie"
37
  msgid "Compress"
38
  msgstr "Comprimeer"
39
 
40
- msgid "Compress all uncompressed sizes"
41
- msgstr "Comprimeer alle ongecomprimeerde afmetingen"
42
 
43
  msgid "Compressed %d out of %d sizes"
44
  msgstr "%d van de %d afmetingen zijn gecomprimeerd"
@@ -52,6 +52,12 @@ msgstr "Gecomprimeerde grootte"
52
  msgid "Latest error"
53
  msgstr "Laatste fout"
54
 
 
 
 
 
 
 
55
  msgid "Credentials are invalid"
56
  msgstr "Ongeldige API-sleutel"
57
 
@@ -102,3 +108,87 @@ msgstr "Kon de metadata niet vinden van het bestand"
102
 
103
  msgid "The API key has been configured in %s"
104
  msgstr "De API-sleutel is geconfigureerd in %s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  msgid "Compress"
38
  msgstr "Comprimeer"
39
 
40
+ msgid "Compress Images"
41
+ msgstr "Comprimeer Afbeeldingen"
42
 
43
  msgid "Compressed %d out of %d sizes"
44
  msgstr "%d van de %d afmetingen zijn gecomprimeerd"
52
  msgid "Latest error"
53
  msgstr "Laatste fout"
54
 
55
+ msgid "Error"
56
+ msgstr "Fout"
57
+
58
+ msgid "Internal error"
59
+ msgstr "Interne fout"
60
+
61
  msgid "Credentials are invalid"
62
  msgstr "Ongeldige API-sleutel"
63
 
108
 
109
  msgid "The API key has been configured in %s"
110
  msgstr "De API-sleutel is geconfigureerd in %s"
111
+
112
+ msgid "Connection status"
113
+ msgstr "Verbinding status"
114
+
115
+ msgid "Dismiss"
116
+ msgstr "Negeer"
117
+
118
+ msgid "TinyPNG API account"
119
+ msgstr "TinyPNG API account"
120
+
121
+ msgid "API connection successful"
122
+ msgstr "API-verbinding succesvol"
123
+
124
+ msgid "API connection unsuccessful"
125
+ msgstr "API-verbinding niet succesvol"
126
+
127
+ msgid "API status could not be checked, enable cURL for more information"
128
+ msgstr "API-status kon niet worden gecontroleerd, schakel cURL in voor meer informatie"
129
+
130
+ msgid "You have made %s compressions this month"
131
+ msgstr "Je hebt deze maand %s compressies uitgevoerd"
132
+
133
+ msgid "You have reached your limit of %s compressions this month"
134
+ msgstr "Je hebt je maandelijkse limiet van %s compressies bereikt"
135
+
136
+ msgid "If you need to compress more images you can change your %s"
137
+ msgstr "Als je meer afbeeldingen wilt comprimeren kun je je %s aanpassen"
138
+
139
+ msgid "Upgrade your %s if you like to compress more images"
140
+ msgstr "Upgrade je %s als je meer afbeeldingen wilt comprimeren"
141
+
142
+ msgid "Please fill in an API key to start compressing images"
143
+ msgstr "Vul een API-sleutel in om te starten met comprimeren"
144
+
145
+ msgid "Compress All Images"
146
+ msgstr "Comprimeer Alle Afbeeldingen"
147
+
148
+ msgid "Compress JPEG & PNG Images"
149
+ msgstr "Comprimeer JPEG & PNG afbeeldingen"
150
+
151
+ msgid "All images are processed"
152
+ msgstr "Alle afbeeldingen zijn verwerkt"
153
+
154
+ msgid "Compressions this month"
155
+ msgstr "Compressies deze maand"
156
+
157
+ msgid "Processing"
158
+ msgstr "Bezig met"
159
+
160
+ msgid "Waiting"
161
+ msgstr "Wachten"
162
+
163
+ msgid "Compressing"
164
+ msgstr "Comprimeren"
165
+
166
+ msgid "compressions"
167
+ msgstr "compressies"
168
+
169
+ msgid "out of"
170
+ msgstr "van de"
171
+
172
+ msgid "Use this tool to compress all images in your media library"
173
+ msgstr "Deze tool comprimeert alle afbeeldingen in je media-bibliotheek"
174
+
175
+ msgid "Only images that have not been compressed will be compressed"
176
+ msgstr "Dit geldt alleen voor de afbeeldingen die nog niet zijn gecomprimeerd"
177
+
178
+ msgid "We have found %d images in your media library"
179
+ msgstr "We hebben %d afbeeldingen in de media-bibliotheek gevonden"
180
+
181
+ msgid "To begin, just press the button below"
182
+ msgstr "Druk op de knop om te starten"
183
+
184
+ msgid "Please be patient while the images are being compressed"
185
+ msgstr "Even geduld terwijl de afbeeldingen worden gecomprimeerd"
186
+
187
+ msgid "This can take a while if you have many images"
188
+ msgstr "Het kan een poos duren als je veel afbeeldingen hebt"
189
+
190
+ msgid "Do not navigate away from this page because it will stop the process"
191
+ msgstr "Navigeer niet van deze pagina want daardoor stopt het proces"
192
+
193
+ msgid "You will be notified via this page when the processing is done"
194
+ msgstr "Je wordt genotificeerd op deze pagina bij voltooing"
src/languages/tiny-compress-images-ru_RU.mo ADDED
Binary file
src/languages/tiny-compress-images-ru_RU.po ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "POT-Creation-Date: \n"
5
+ "PO-Revision-Date: \n"
6
+ "Last-Translator: Oleg Shalomanov <shalomanov@gmail.com>\n"
7
+ "Language-Team: \n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=UTF-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Generator: Poedit 1.6.5\n"
12
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
13
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
14
+ "Language: ru_RU\n"
15
+
16
+ msgid "PNG and JPEG compression"
17
+ msgstr "Сжатие PNG и JPEG"
18
+
19
+ msgid "Multisite PNG and JPEG compression"
20
+ msgstr "PNG и JPEG сжатие для Multisite"
21
+
22
+ msgid "Visit %s to get an API key"
23
+ msgstr "Посетите %s, чтобы получить API ключ"
24
+
25
+ msgid "Visit %s to view your usage or upgrade your account"
26
+ msgstr "Посетите %s, чтобы посмотреть свою статистику использования сервиса и повысить статус аккаунта"
27
+
28
+ msgid "TinyPNG Developer section"
29
+ msgstr "раздел TinyPNG для разработчиков"
30
+
31
+ msgid "TinyPNG API key"
32
+ msgstr "TinyPNG API ключ"
33
+
34
+ msgid "Multisite API key"
35
+ msgstr "Multisite API ключ"
36
+
37
+ msgid "File compression"
38
+ msgstr "Сжатие файлов"
39
+
40
+ msgid "original"
41
+ msgstr "оригинальное изображение"
42
+
43
+ msgid "You can choose to compress different image sizes created by WordPress here"
44
+ msgstr "Здесь вы можете выбрать, какие размеры изображений сжимать"
45
+
46
+ msgid "Remember each additional image size will affect your TinyPNG monthly usage"
47
+ msgstr "Помните, каждый дополнительный типоразмер влияет на месячное использование сервиса TinyPNG"
48
+
49
+ msgid "Compression"
50
+ msgstr "Сжатие"
51
+
52
+ msgid "Compress"
53
+ msgstr "Сжать"
54
+
55
+ msgid "Compress all"
56
+ msgstr "Сжать все"
57
+
58
+ msgid "Compressed %d out of %d sizes"
59
+ msgstr "Сжато %d из %d типоразмера(-ов)"
60
+
61
+ msgid "Total size"
62
+ msgstr "Было"
63
+
64
+ msgid "Compressed size"
65
+ msgstr "Стало"
66
+
67
+ msgid "Latest error"
68
+ msgstr "Последняя ошибка"
69
+
70
+ msgid "Error"
71
+ msgstr "Oшибка"
72
+
73
+ msgid "Internal error"
74
+ msgstr "Oшибка"
75
+
76
+ msgid "Credentials are invalid"
77
+ msgstr "Параметры доступа некорректны"
78
+
79
+ msgid "Your monthly limit has been exceeded"
80
+ msgstr "Ваш месячный лимит израсходован"
81
+
82
+ msgid "File is empty"
83
+ msgstr "Файл пустой"
84
+
85
+ msgid "Does not appear to be a PNG or JPEG file"
86
+ msgstr "Файл не PNG или JPEG"
87
+
88
+ msgid "CMYK color space is not supported"
89
+ msgstr "Цветовая модель CMYK не поддерживается"
90
+
91
+ msgid "Image appears corrupt"
92
+ msgstr "Изображение повреждено"
93
+
94
+ msgid "Compression failed"
95
+ msgstr "Сжатие не удалось"
96
+
97
+ msgid "No HTTP client is available (cURL or fopen)"
98
+ msgstr "Нет HTTP клиента (нужны cURL или fopen)"
99
+
100
+ msgid "Could not find output url"
101
+ msgstr "Не могу найти url результата"
102
+
103
+ msgid "Could not download output"
104
+ msgstr "Не могу загрузить результат"
105
+
106
+ msgid "File does not exists"
107
+ msgstr "Файл не существует или не найден плагином"
108
+
109
+ msgid "Could not decode JSON"
110
+ msgstr "Не могу раскодировать JSON"
111
+
112
+ msgid "Could not compress, enable cURL for detailed error"
113
+ msgstr "Не могу сжать. Подключите cURL для деталей"
114
+
115
+ msgid "You don't have permission to work with uploaded files"
116
+ msgstr "У вас нет разрешения работать с загруженными файлами"
117
+
118
+ msgid "Not a valid media file"
119
+ msgstr "Неподходящий медиа-файл"
120
+
121
+ msgid "Could not find metadata of media file"
122
+ msgstr "Не найдены метаданные файла"
123
+
124
+ msgid "The API key has been configured in %s"
125
+ msgstr "API ключ был определен в %s"
src/scripts/admin.js CHANGED
@@ -1,24 +1,146 @@
1
  (function() {
2
 
 
 
 
 
3
  function compress_image(event) {
4
- var element = jQuery(event.target);
5
- element.attr('disabled', 'disabled');
6
- element.closest('td').find('.spinner').css('display', 'inline');
7
- jQuery.post(
8
- ajaxurl, {
9
- 'action': 'tiny_compress_image',
10
- 'id': element.data('id') || element.attr('data-id')
11
- }, function (response) {
12
- element.closest('td').html(response);
 
 
 
 
 
 
 
 
13
  }
14
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
 
17
  if (adminpage === "upload-php") {
18
  if (typeof jQuery.fn.on === "function") {
19
- jQuery('table').on('click', 'button.tiny-compress', compress_image);
20
  } else {
21
- jQuery('button.tiny-compress').live('click', compress_image);
22
  }
23
 
24
  if (typeof jQuery.fn.prop === "function") {
@@ -27,7 +149,18 @@
27
  jQuery('button.tiny-compress').attr('disabled', null)
28
  }
29
 
30
- jQuery('<option>').val('tiny_bulk_compress').text(tinyCompressL10n.bulkAction).appendTo('select[name="action"]');
31
- jQuery('<option>').val('tiny_bulk_compress').text(tinyCompressL10n.bulkAction).appendTo('select[name="action2"]');
 
 
 
 
32
  }
33
- }).call();
 
 
 
 
 
 
 
1
  (function() {
2
 
3
+ function check_wp_version(version) {
4
+ return parseFloat(tinyCompress.wpVersion) >= version
5
+ }
6
+
7
  function compress_image(event) {
8
+ var element = jQuery(event.target)
9
+ element.attr('disabled', 'disabled')
10
+ element.closest('td').find('.spinner').removeClass('hidden')
11
+ jQuery.ajax({
12
+ url: ajaxurl,
13
+ type: "POST",
14
+ data: {
15
+ _nonce: tinyCompress.nonce,
16
+ action: 'tiny_compress_image',
17
+ id: element.data('id') || element.attr('data-id')
18
+ },
19
+ success: function(data) {
20
+ element.closest('td').html(data)
21
+ },
22
+ error: function() {
23
+ element.removeAttr('disabled')
24
+ element.closest('td').find('.spinner').addClass('hidden')
25
  }
26
+ })
27
+ }
28
+
29
+ function dismiss_notice(event) {
30
+ var element = jQuery(event.target)
31
+ var notice = element.closest(".tiny-notice")
32
+ element.attr('disabled', 'disabled')
33
+ jQuery.ajax({
34
+ url: ajaxurl,
35
+ type: "POST",
36
+ dataType: "json",
37
+ data: {
38
+ _nonce: tinyCompress.nonce,
39
+ action: 'tiny_dismiss_notice',
40
+ name: notice.data('name') || notice.attr('data-name')
41
+ },
42
+ success: function(data) {
43
+ if (data) {
44
+ notice.remove()
45
+ }
46
+ },
47
+ error: function() {
48
+ element.removeAttr('disabled')
49
+ }
50
+ })
51
+ return false
52
+ }
53
+
54
+ function bulk_compress_callback(error, data, items, i) {
55
+ var row = jQuery(jQuery('#media-items').children("div")[i])
56
+ var status
57
+
58
+ if (check_wp_version(3.3)) {
59
+ status = row.find('.bar')
60
+ } else {
61
+ row.find('.bar').remove()
62
+ status = row.find('.percent')
63
+ }
64
+
65
+ if (data.thumbnail) {
66
+ var img = jQuery('<img class="pinkynail">')
67
+ img.attr("src", data.thumbnail)
68
+ row.prepend(img)
69
+ }
70
+
71
+ if (error) {
72
+ status.addClass('failed')
73
+ row.find('.percent').html(tinyCompress.L10nInternalError)
74
+ row.find('.progress').attr("title", error.toString())
75
+ } else if (data.error) {
76
+ status.addClass('failed')
77
+ row.find('.percent').html(tinyCompress.L10nError)
78
+ row.find('.progress').attr("title", data.error)
79
+ } else if (data.failed > 0) {
80
+ status.addClass('failed')
81
+ row.find('.bar').css('width', '100%')
82
+ row.find('.percent').html(data.success + " " + tinyCompress.L10nCompressions)
83
+ row.find('.progress').attr("title", data.message)
84
+ } else {
85
+ status.addClass('success')
86
+ row.find('.bar').css('width', '100%')
87
+ row.find('.percent').html(data.success + " " + tinyCompress.L10nCompressions)
88
+ }
89
+
90
+ if (data.status) {
91
+ jQuery('#tiny-status span').html(data.status)
92
+ }
93
+
94
+ if (items[++i]) {
95
+ bulk_compress_item(items, i)
96
+ } else {
97
+ var message = jQuery('<div class="updated"><p></p></div>');
98
+ message.find('p').html(tinyCompress.L10nAllDone)
99
+ message.insertAfter(jQuery("#tiny-bulk-compress h2"))
100
+ }
101
+ }
102
+
103
+ function bulk_compress_item(items, i) {
104
+ var item = items[i]
105
+ var row = jQuery(jQuery('#media-items').children("div")[i])
106
+ row.find('.percent').html(tinyCompress.L10nCompressing)
107
+ jQuery.ajax({
108
+ url: ajaxurl,
109
+ type: "POST",
110
+ dataType: "json",
111
+ data: {
112
+ _nonce: tinyCompress.nonce,
113
+ action: 'tiny_compress_image',
114
+ id: items[i].ID,
115
+ json: true
116
+ },
117
+ success: function(data) { bulk_compress_callback(null, data, items, i)},
118
+ error: function(xhr, textStatus, errorThrown) { bulk_compress_callback(errorThrown, {}, items, i) }
119
+ })
120
+ jQuery('#tiny-progress span').html(i + 1)
121
+ }
122
+
123
+ function bulk_compress(items) {
124
+ var list = jQuery('#media-items')
125
+ var row
126
+ for (var i = 0; i < items.length; i++) {
127
+ if (check_wp_version(3.3)) {
128
+ row = jQuery('<div class="media-item"><div class="progress"><div class="percent"></div><div class="bar"></div></div><div class="filename"></div></div>')
129
+ } else {
130
+ row = jQuery('<div class="media-item" style="box-shadow: none"><div class="progress"><div class="bar"></div></div><div class="percent"></div><div class="filename"></div></div>')
131
+ }
132
+ row.find('.percent').html(tinyCompress.L10nWaiting)
133
+ row.find('.filename').html(items[i].post_title)
134
+ list.append(row)
135
+ }
136
+ bulk_compress_item(items, 0)
137
  }
138
 
139
  if (adminpage === "upload-php") {
140
  if (typeof jQuery.fn.on === "function") {
141
+ jQuery('table').on('click', 'button.tiny-compress', compress_image)
142
  } else {
143
+ jQuery('button.tiny-compress').live('click', compress_image)
144
  }
145
 
146
  if (typeof jQuery.fn.prop === "function") {
149
  jQuery('button.tiny-compress').attr('disabled', null)
150
  }
151
 
152
+ jQuery('<option>').val('tiny_bulk_compress').text(tinyCompress.L10nBulkAction).appendTo('select[name="action"]')
153
+ jQuery('<option>').val('tiny_bulk_compress').text(tinyCompress.L10nBulkAction).appendTo('select[name="action2"]')
154
+ }
155
+
156
+ if (adminpage === "options-media-php") {
157
+ jQuery('#tiny-compress-status').load(ajaxurl + '?action=tiny_compress_status')
158
  }
159
+
160
+ jQuery('.tiny-notice a.tiny-dismiss').click(dismiss_notice)
161
+ jQuery(function() {
162
+ jQuery('.tiny-notice.is-dismissible button').unbind('click').click(dismiss_notice)
163
+ })
164
+
165
+ window.tinyBulkCompress = bulk_compress
166
+ }).call()
src/styles/admin.css CHANGED
@@ -1,3 +1,53 @@
1
- .tiny-compress-images .spinner {
2
  display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  }
1
+ .tiny-compress-images .spinner.hidden {
2
  display: none;
3
+ visibility: hidden;
4
+ float: none;
5
+ margin-top: 0;
6
+ }
7
+
8
+ .tiny-compress-images .spinner {
9
+ display: inline-block;
10
+ visibility: visible;
11
+ float: none;
12
+ margin-top: 0;
13
+ }
14
+
15
+ #tiny-compress-status .spinner {
16
+ display: inline;
17
+ visibility: visible;
18
+ float: left;
19
+ margin: 0;
20
+ }
21
+
22
+ #tiny-bulk-compress #media-items .bar.failed {
23
+ background-color: #DD3D36;
24
+ }
25
+
26
+ #tiny-bulk-compress #media-items .percent.failed {
27
+ color: #DD3D36;
28
+ }
29
+
30
+ #tiny-bulk-compress .media-item {
31
+ box-shadow: 0px 1px 0px #DFDFDF;
32
+ min-height: 36px;
33
+ margin-bottom: 1px;
34
+ position: relative;
35
+ width: 100%;
36
+ background: none repeat scroll 0% 0% #FFF;
37
+ }
38
+
39
+ #tiny-bulk-compress .progress~.percent {
40
+ float: right;
41
+ line-height: 36px;
42
+ margin-right: 20px;
43
+ }
44
+
45
+ #tiny-progress p, #tiny-status p {
46
+ font-size: 120%;
47
+ }
48
+
49
+ #tiny-progress span, #tiny-status span {
50
+ background: none repeat scroll 0% 0% #FFF;
51
+ box-shadow: 0px 1px 0px #DFDFDF;
52
+ padding: 5px;
53
  }
test/fixtures/{example-tinypng.png → input-example.jpg} RENAMED
File without changes
test/fixtures/{example-tinyjpg.jpg → input-example.png} RENAMED
File without changes
test/fixtures/{example-large.png → input-large.png} RENAMED
File without changes
test/fixtures/tiny-config.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class Tiny_Config {
4
+ const URL = 'http://webservice/shrink';
5
+ }
test/fixtures/tinypng-api.ini DELETED
@@ -1,2 +0,0 @@
1
- [api]
2
- url = "http://webservice/shrink"
 
 
test/helpers/compress.php DELETED
@@ -1,31 +0,0 @@
1
- <?php
2
- function compressTestFile($file) {
3
- if (!preg_match('#test(-(\S+))?[.](png|jpe?g)$#', $file, $match)) {
4
- throw new TinyPNGCompressException('Does not appear to be a PNG or JPEG file', 'BadSignature');
5
- }
6
-
7
- switch ($match[2]) {
8
- case "thumbnail":
9
- return array('input' => array('size' => 100), 'output' => array('size' => 81));
10
- case "medium":
11
- return array('input' => array('size' => 1000), 'output' => array('size' => 768));
12
- case "large":
13
- return array('input' => array('size' => 10000), 'output' => array('size' => 6789));
14
- case "post-thumbnail":
15
- return array('input' => array('size' => 1234), 'output' => array('size' => 1000));
16
- default:
17
- return array('input' => array('size' => 12345), 'output' => array('size' => 10000));
18
- }
19
- }
20
-
21
- function getTestMetadata() {
22
- return array(
23
- 'file' => '14/01/test.png',
24
- 'sizes' => array(
25
- 'thumbnail' => array('file' => 'test-thumbnail.png'),
26
- 'medium' => array('file' => 'test-medium.png'),
27
- 'large' => array('file' => 'test-large.png'),
28
- 'post-thumbnail' => array('file' => 'test-post-thumbnail.png'),
29
- )
30
- );
31
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test/helpers/setup.php CHANGED
@@ -50,13 +50,13 @@ function backup_wordpress_site() {
50
 
51
  function set_test_webservice_url() {
52
  $config_dir = dirname(__FILE__) . '/../../src/config';
53
- shell_exec('mv ' . $config_dir . '/tinypng-api.ini ' . $config_dir . '/tinypng-api.ini.bak');
54
- shell_exec('cp ' . dirname(__FILE__) . '/../fixtures/tinypng-api.ini ' . $config_dir . '/tinypng-api.ini');
55
  }
56
 
57
  function restore_webservice_url() {
58
  $config_dir = dirname(__FILE__) . '/../../src/config';
59
- shell_exec('test -f ' . $config_dir . '/tinypng-api.ini.bak && mv ' . $config_dir . '/tinypng-api.ini.bak ' . $config_dir . '/tinypng-api.ini');
60
  }
61
 
62
  function set_siteurl($site_url) {
@@ -66,6 +66,23 @@ function set_siteurl($site_url) {
66
  $statement->execute();
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  function is_wordpress_setup() {
70
  $db = new mysqli(getenv('HOST_IP'), 'root', getenv('MYSQL_ROOT_PASSWORD'));
71
  if ($result = $db->query("SELECT * FROM information_schema.tables WHERE table_schema = '" . getenv('WORDPRESS_DATABASE') . "'")) {
@@ -100,20 +117,6 @@ function setup_wordpress_site($driver) {
100
  }
101
  }
102
 
103
- function clear_uploads($driver) {
104
- media_bulk_action($driver, 'delete');
105
- }
106
-
107
- function media_bulk_action($driver, $action) {
108
- $driver->get(wordpress('/wp-admin/upload.php?mode=list'));
109
- $checkboxes = $driver->findElements(WebDriverBy::cssSelector('th input[type="checkbox"]'));
110
- if (count($checkboxes) > 0) {
111
- $checkboxes[0]->click();
112
- $driver->findElement(WebDriverBy::cssSelector('select[name="action"] option[value="' . $action . '"]'))->click();
113
- $driver->findElement(WebDriverBy::cssSelector('div.actions input[value="Apply"]'))->click();
114
- }
115
- }
116
-
117
  function login($driver) {
118
  $driver->get(wordpress('/wp-login.php'));
119
  $driver->findElement(WebDriverBy::tagName('body'))->click();
@@ -140,11 +143,30 @@ function activate_plugin($driver) {
140
  var_dump($driver->getPageSource());
141
  throw new UnexpectedValueException('Activating plugin failed.');
142
  }
 
143
  }
144
 
145
- register_shutdown_function('restore_wordpress');
 
 
 
 
146
 
147
- $global_phantom_host = 'http://127.0.0.1:4444/wd/hub';
148
- $global_driver = RemoteWebDriver::create($global_phantom_host, DesiredCapabilities::firefox());
 
 
 
 
 
 
 
 
 
 
149
  $global_session_id = $global_driver->getSessionID();
 
 
 
 
150
  configure_wordpress_for_testing($global_driver);
50
 
51
  function set_test_webservice_url() {
52
  $config_dir = dirname(__FILE__) . '/../../src/config';
53
+ shell_exec('mv ' . $config_dir . '/tiny-config.php ' . $config_dir . '/tiny-config.php.bak');
54
+ shell_exec('cp ' . dirname(__FILE__) . '/../fixtures/tiny-config.php ' . $config_dir . '/tiny-config.php');
55
  }
56
 
57
  function restore_webservice_url() {
58
  $config_dir = dirname(__FILE__) . '/../../src/config';
59
+ shell_exec('test -f ' . $config_dir . '/tiny-config.php.bak && mv ' . $config_dir . '/tiny-config.php.bak ' . $config_dir . '/tiny-config.php');
60
  }
61
 
62
  function set_siteurl($site_url) {
66
  $statement->execute();
67
  }
68
 
69
+ function clear_settings() {
70
+ $db = new mysqli(getenv('HOST_IP'), 'root', getenv('MYSQL_ROOT_PASSWORD'), getenv('WORDPRESS_DATABASE'));
71
+ $statement = $db->prepare("DELETE FROM wp_options WHERE option_name LIKE 'tinypng_%'");
72
+ $statement->execute();
73
+ $statement = $db->prepare("DELETE FROM wp_usermeta WHERE meta_key LIKE 'tinypng_%'");
74
+ $statement->execute();
75
+ }
76
+
77
+ function clear_uploads() {
78
+ $db = new mysqli(getenv('HOST_IP'), 'root', getenv('MYSQL_ROOT_PASSWORD'), getenv('WORDPRESS_DATABASE'));
79
+ $statement = $db->prepare("DELETE wp_postmeta FROM wp_postmeta JOIN wp_posts ON wp_posts.ID = wp_postmeta.post_id WHERE wp_posts.post_type = 'attachment'");
80
+ $statement->execute();
81
+ $statement = $db->prepare("DELETE FROM wp_posts WHERE wp_posts.post_type = 'attachment'");
82
+ $statement->execute();
83
+ shell_exec('docker exec -it wordpress' . getenv('WORDPRESS_VERSION') . ' rm -rf wp-content/uploads');
84
+ }
85
+
86
  function is_wordpress_setup() {
87
  $db = new mysqli(getenv('HOST_IP'), 'root', getenv('MYSQL_ROOT_PASSWORD'));
88
  if ($result = $db->query("SELECT * FROM information_schema.tables WHERE table_schema = '" . getenv('WORDPRESS_DATABASE') . "'")) {
117
  }
118
  }
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  function login($driver) {
121
  $driver->get(wordpress('/wp-login.php'));
122
  $driver->findElement(WebDriverBy::tagName('body'))->click();
143
  var_dump($driver->getPageSource());
144
  throw new UnexpectedValueException('Activating plugin failed.');
145
  }
146
+ $driver->get(wordpress('/wp-admin/upload.php?mode=list'));
147
  }
148
 
149
+ function close_webdriver() {
150
+ if (isset($GLOBALS['global_session_id']) && isset($GLOBALS['global_webdriver_host'])) {
151
+ RemoteWebDriver::createBySessionId($GLOBALS['global_session_id'], $GLOBALS['global_webdriver_host'])->close();
152
+ }
153
+ }
154
 
155
+ function reset_webservice() {
156
+ $request = curl_init();
157
+ curl_setopt_array($request, array(
158
+ CURLOPT_URL => 'http://' . getenv('HOST_IP') .':8080/reset',
159
+ ));
160
+
161
+ $response = curl_exec($request);
162
+ curl_close($request);
163
+ }
164
+
165
+ $global_webdriver_host = 'http://127.0.0.1:4444/wd/hub';
166
+ $global_driver = RemoteWebDriver::create($global_webdriver_host, DesiredCapabilities::firefox());
167
  $global_session_id = $global_driver->getSessionID();
168
+
169
+ register_shutdown_function('close_webdriver');
170
+ register_shutdown_function('restore_wordpress');
171
+
172
  configure_wordpress_for_testing($global_driver);
test/helpers/wordpress.php CHANGED
@@ -1,5 +1,8 @@
1
  <?php
2
 
 
 
 
3
  class WordPressOptions {
4
  private $values;
5
 
@@ -31,6 +34,9 @@ class WordPressOptions {
31
  }
32
 
33
  class WordPressStubs {
 
 
 
34
  private $initFunctions;
35
  private $admin_initFunctions;
36
  private $options;
@@ -38,7 +44,9 @@ class WordPressStubs {
38
  private $calls;
39
  private $stubs;
40
 
41
- public function __construct() {
 
 
42
  $this->addMethod('add_action');
43
  $this->addMethod('add_filter');
44
  $this->addMethod('register_setting');
@@ -56,7 +64,16 @@ class WordPressStubs {
56
  $this->addMethod('wp_upload_dir');
57
  $this->addMethod('plugin_basename');
58
  $this->addMethod('is_multisite');
 
 
 
59
  $this->defaults();
 
 
 
 
 
 
60
  }
61
 
62
  public function defaults() {
@@ -67,14 +84,6 @@ class WordPressStubs {
67
  $GLOBALS['_wp_additional_image_sizes'] = array();
68
  }
69
 
70
- public function clear() {
71
- $this->defaults();
72
- foreach (array_keys($this->calls) as $method) {
73
- $this->calls[$method] = array();
74
- $this->stubs[$method] = array();
75
- }
76
- }
77
-
78
  public function call($method, $args) {
79
  $this->calls[$method][] = $args;
80
  if ('add_action' === $method) {
@@ -94,6 +103,10 @@ class WordPressStubs {
94
  return call_user_func_array(array($this, 'updateMetadata'), $args);
95
  } elseif ('get_intermediate_image_sizes' === $method) {
96
  return array_merge(array('thumbnail', 'medium', 'large'), array_keys($GLOBALS['_wp_additional_image_sizes']));
 
 
 
 
97
  } elseif ($this->stubs[$method]) {
98
  return call_user_func_array($this->stubs[$method], $args);
99
  }
@@ -142,7 +155,38 @@ class WordPressStubs {
142
  public function stub($method, $func) {
143
  $this->stubs[$method] = $func;
144
  }
145
- }
146
 
 
 
 
 
 
 
 
147
 
148
- $GLOBALS['wp'] = new WordPressStubs();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ use org\bovigo\vfs\vfsStream;
4
+ use org\bovigo\vfs\content\LargeFileContent;
5
+
6
  class WordPressOptions {
7
  private $values;
8
 
34
  }
35
 
36
  class WordPressStubs {
37
+ const UPLOAD_DIR = 'wp-content/uploads';
38
+
39
+ private $vfs;
40
  private $initFunctions;
41
  private $admin_initFunctions;
42
  private $options;
44
  private $calls;
45
  private $stubs;
46
 
47
+ public function __construct($vfs) {
48
+ $GLOBALS['wp'] = $this;
49
+ $this->vfs = $vfs;
50
  $this->addMethod('add_action');
51
  $this->addMethod('add_filter');
52
  $this->addMethod('register_setting');
64
  $this->addMethod('wp_upload_dir');
65
  $this->addMethod('plugin_basename');
66
  $this->addMethod('is_multisite');
67
+ $this->addMethod('current_user_can');
68
+ $this->addMethod('wp_get_attachment_metadata');
69
+ $this->addMethod('is_admin');
70
  $this->defaults();
71
+ $this->create_filesystem();
72
+ }
73
+
74
+ public function create_filesystem() {
75
+ vfsStream::newDirectory(self::UPLOAD_DIR)
76
+ ->at($this->vfs);
77
  }
78
 
79
  public function defaults() {
84
  $GLOBALS['_wp_additional_image_sizes'] = array();
85
  }
86
 
 
 
 
 
 
 
 
 
87
  public function call($method, $args) {
88
  $this->calls[$method][] = $args;
89
  if ('add_action' === $method) {
103
  return call_user_func_array(array($this, 'updateMetadata'), $args);
104
  } elseif ('get_intermediate_image_sizes' === $method) {
105
  return array_merge(array('thumbnail', 'medium', 'large'), array_keys($GLOBALS['_wp_additional_image_sizes']));
106
+ } elseif ('wp_upload_dir' === $method) {
107
+ return array('basedir' => $this->vfs->url() . '/' . self::UPLOAD_DIR, 'baseurl' => '/' . self::UPLOAD_DIR);
108
+ } elseif ('is_admin' === $method) {
109
+ return true;
110
  } elseif ($this->stubs[$method]) {
111
  return call_user_func_array($this->stubs[$method], $args);
112
  }
155
  public function stub($method, $func) {
156
  $this->stubs[$method] = $func;
157
  }
 
158
 
159
+ public function createImages($sizes=null, $original_size=12345, $path='14/01', $name='test') {
160
+ vfsStream::newDirectory(self::UPLOAD_DIR . "/$path")->at($this->vfs);
161
+ $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
162
+
163
+ vfsStream::newFile("$name.png")
164
+ ->withContent(new LargeFileContent($original_size))
165
+ ->at($dir);
166
 
167
+ if (is_null($sizes)) {
168
+ $sizes = array('thumbnail' => 100, 'medium' => 1000 , 'large' => 10000, 'post-thumbnail' => 1234);
169
+ }
170
+
171
+ foreach ($sizes as $key => $size) {
172
+ vfsStream::newFile("$name-$key.png")
173
+ ->withContent(new LargeFileContent($size))
174
+ ->at($dir);
175
+ }
176
+ }
177
+
178
+ public function getTestMetadata($path='14/01', $name='test') {
179
+ $metadata = array('file' => "$path/$name.png", 'sizes' => array());
180
+
181
+ $regex = '#^' . preg_quote($name) .'-([^.]+)[.](png|jpe?g)$#';
182
+ $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
183
+ foreach ($dir->getChildren() as $child) {
184
+ $file = $child->getName();
185
+ if (preg_match($regex, $file, $match)) {
186
+ $metadata['sizes'][$match[1]] = array('file' => $file);
187
+ }
188
+ }
189
+
190
+ return $metadata;
191
+ }
192
+ }
test/integration/BulkCompressIntegrationTest.php CHANGED
@@ -9,28 +9,68 @@ class BulkCompressIntegrationTest extends IntegrationTestCase {
9
  }
10
 
11
  public function tearDown() {
12
- $this->enable_compression_sizes(array('0', 'thumbnail', 'medium', 'large', 'post-thumbnail'));
13
- clear_uploads(self::$driver);
 
14
  }
15
 
16
- public function testBulkCompressActionShouldBePresent()
17
- {
18
- $this->upload_image(dirname(__FILE__) . '/../fixtures/example-tinypng.png');
19
- self::$driver->get(wordpress('/wp-admin/upload.php?mode=list'));
20
- $this->assertEquals('Compress all uncompressed sizes', self::$driver->findElement(
21
  WebDriverBy::cssSelector('select[name="action"] option[value="tiny_bulk_compress"]')
22
  )->getText());
23
  }
24
 
25
- public function testBulkCompressShouldCompressUncompressedSizes() {
26
- $this->enable_compression_sizes(array('thumbnail'));
27
-
28
  $this->set_api_key('PNG123');
29
- $this->upload_image(dirname(__FILE__) . '/../fixtures/example-large.png');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- $this->enable_compression_sizes(array('thumbnail', 'medium'));
32
- media_bulk_action(self::$driver, 'tiny_bulk_compress');
 
33
 
34
- $this->assertContains('Compressed 2 out of 2 sizes', self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
 
35
  }
36
  }
9
  }
10
 
11
  public function tearDown() {
12
+ clear_settings();
13
+ clear_uploads();
14
+ reset_webservice();
15
  }
16
 
17
+ public function testBulkCompressActionShouldBePresentInMedia() {
18
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
19
+ $this->assertEquals('Compress Images', self::$driver->findElement(
 
 
20
  WebDriverBy::cssSelector('select[name="action"] option[value="tiny_bulk_compress"]')
21
  )->getText());
22
  }
23
 
24
+ private function prepare($normal=1, $large=0) {
 
 
25
  $this->set_api_key('PNG123');
26
+ $this->enable_compression_sizes(array());
27
+
28
+ for ($i = 0; $i < $normal; $i++) {
29
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
30
+ }
31
+ for ($i = 0; $i < $large; $i++) {
32
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-large.png');
33
+ }
34
+
35
+ $this->enable_compression_sizes(array('thumbnail', 'medium', 'large'));
36
+ }
37
+
38
+ public function testBulkCompressShouldFromMediaShouldOnlyCompressSelected() {
39
+ $this->prepare(1, 2);
40
+
41
+ self::$driver->get(wordpress('/wp-admin/upload.php?orderby=title&order=asc'));
42
+ $checkboxes = self::$driver->findElements(WebDriverBy::cssSelector('tbody input[type="checkbox"]'));
43
+ $checkboxes[0]->click();
44
+
45
+ self::$driver->findElement(WebDriverBy::cssSelector('select[name="action"] option[value="tiny_bulk_compress"]'))->click();
46
+ self::$driver->findElement(WebDriverBy::cssSelector('div.actions input[value="Apply"]'))->click();
47
+
48
+ self::$driver->wait(3)->until(WebDriverExpectedCondition::textToBePresentInElement(
49
+ WebDriverBy::cssSelector('.updated'), 'All images are processed'));
50
+
51
+ $this->assertEquals('1', self::$driver->findElement(WebDriverBy::cssSelector('#tiny-progress span'))->getText());
52
+ $this->assertEquals('input-example', self::$driver->findElement(WebDriverBy::cssSelector('.media-item .filename'))->getText());
53
+ }
54
+
55
+ public function testBulkCompressShouldCompressAll() {
56
+ $this->prepare(1, 1);
57
+
58
+ self::$driver->get(wordpress('/wp-admin/tools.php?page=tiny-bulk-compress.php'));
59
+ $elements = self::$driver->findElements(WebDriverBy::cssSelector('#tiny-bulk-compress p'));
60
+ $this->assertContains('2 images', $elements[1]->getText());
61
+
62
+ self::$driver->findElement(WebDriverBy::cssSelector('#tiny-bulk-compress button'))->click();
63
+ self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
64
+ WebDriverBy::cssSelector('.updated'), 'All images are processed'));
65
+
66
+ $elements = self::$driver->findElements(WebDriverBy::cssSelector('.media-item .filename'));
67
+ $filenames = array_map('innerText', $elements);
68
 
69
+ $this->assertEquals(2, count($filenames));
70
+ $this->assertContains('input-large', $filenames);
71
+ $this->assertContains('input-example', $filenames);
72
 
73
+ $this->assertEquals('2', self::$driver->findElement(WebDriverBy::cssSelector('#tiny-progress span'))->getText());
74
+ $this->assertEquals('5', self::$driver->findElement(WebDriverBy::cssSelector('#tiny-status span'))->getText());
75
  }
76
  }
test/integration/CompressIntegrationTest.php CHANGED
@@ -9,26 +9,62 @@ class CompressIntegrationTest extends IntegrationTestCase {
9
  }
10
 
11
  public function tearDown() {
12
- clear_uploads(self::$driver);
 
13
  }
14
 
15
  public function testInvalidCredentialsShouldStillUploadImage()
16
  {
17
  $this->set_api_key('1234');
18
- $this->upload_image(dirname(__FILE__) . '/../fixtures/example-tinypng.png');
19
- $this->assertContains('example-tinypng', self::$driver->findElement(WebDriverBy::xpath('//img[contains(@src, "example-tinypng")]'))->getAttribute('src'));
 
20
  }
21
 
22
  public function testInvalidCredentialsShouldShowError()
23
  {
24
  $this->set_api_key('1234');
25
- $this->upload_image(dirname(__FILE__) . '/../fixtures/example-tinypng.png');
26
- $this->assertContains('Latest error: Credentials are invalid', self::$driver->findElement(WebDriverBy::cssSelector('span.error'))->getText());
 
27
  }
28
 
29
  public function testShrink() {
30
  $this->set_api_key('PNG123');
31
- $this->upload_image(dirname(__FILE__) . '/../fixtures/example-tinypng.png');
32
- $this->assertContains('Compressed size', self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
  }
9
  }
10
 
11
  public function tearDown() {
12
+ clear_settings();
13
+ clear_uploads();
14
  }
15
 
16
  public function testInvalidCredentialsShouldStillUploadImage()
17
  {
18
  $this->set_api_key('1234');
19
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
20
+ $this->assertContains('input-example',
21
+ self::$driver->findElement(WebDriverBy::xpath('//img[contains(@src, "input-example")]'))->getAttribute('src'));
22
  }
23
 
24
  public function testInvalidCredentialsShouldShowError()
25
  {
26
  $this->set_api_key('1234');
27
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
28
+ $this->assertContains('Latest error: Credentials are invalid',
29
+ self::$driver->findElement(WebDriverBy::cssSelector('span.error'))->getText());
30
  }
31
 
32
  public function testShrink() {
33
  $this->set_api_key('PNG123');
34
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
35
+ $this->assertContains('Compressed size',
36
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
37
+ }
38
+
39
+ public function testCompressButton() {
40
+ $this->enable_compression_sizes(array('medium'));
41
+ $this->set_api_key('PNG123');
42
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
43
+ $this->enable_compression_sizes(array('medium', 'large'));
44
+
45
+ self::$driver->get(wordpress('/wp-admin/upload.php'));
46
+ $this->assertContains('Compressed 1 out of 2 sizes',
47
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images'))->getText());
48
+ self::$driver->findElement(WebDriverBy::cssSelector('td.tiny-compress-images button'))->click();
49
+ self::$driver->wait(2)->until(WebDriverExpectedCondition::textToBePresentInElement(
50
+ WebDriverBy::cssSelector('td.tiny-compress-images'), 'Compressed 2 out of 2 sizes'));
51
+ }
52
+
53
+ public function testLimitReached() {
54
+ $this->set_api_key('LIMIT123');
55
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
56
+ $this->assertContains('You have reached your limit',
57
+ self::$driver->findElement(WebDriverBy::cssSelector('div.error p'))->getText());
58
+ }
59
+
60
+ public function testLimitReachedDismisses() {
61
+ $this->set_api_key('LIMIT123');
62
+ $this->upload_image(dirname(__FILE__) . '/../fixtures/input-example.png');
63
+ self::$driver->findElement(WebDriverBy::cssSelector('.tiny-notice button, .tiny-notice a.tiny-dismiss'))->click();
64
+ self::$driver->wait(2)->until(WebDriverExpectedCondition::invisibilityOfElementWithText(
65
+ WebDriverBy::cssSelector('.tiny-dismiss'), 'Dismiss'));
66
+
67
+ self::$driver->get(wordpress('/wp-admin/options-media.php'));
68
+ $this->assertEquals(0, count(self::$driver->findElements(WebDriverBy::cssSelector('div.error p'))));
69
  }
70
  }
test/integration/IntegrationTestCase.php CHANGED
@@ -8,7 +8,7 @@ abstract class IntegrationTestCase extends PHPUnit_Framework_TestCase {
8
  protected static $driver;
9
 
10
  public static function setUpBeforeClass() {
11
- self::$driver = RemoteWebDriver::createBySessionId($GLOBALS['global_session_id'], $GLOBALS['global_phantom_host']);
12
  }
13
 
14
  protected function upload_image($path) {
@@ -33,14 +33,20 @@ abstract class IntegrationTestCase extends PHPUnit_Framework_TestCase {
33
  }
34
 
35
  protected function set_api_key($api_key) {
36
- self::$driver->get(wordpress('/wp-admin/options-media.php'));
 
 
 
37
  self::$driver->findElement(WebDriverBy::name('tinypng_api_key'))->clear()->sendKeys($api_key);
38
  self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
39
  return self::$driver->findElement(WebDriverBy::name('tinypng_api_key'));
40
  }
41
 
42
  protected function enable_compression_sizes($sizes) {
43
- self::$driver->get(wordpress('/wp-admin/options-media.php'));
 
 
 
44
  $elements = self::$driver->findElements(WebDriverBy::xpath('//input[starts-with(@id, "tinypng_sizes_")]'));
45
  foreach($elements as $element) {
46
  $size = str_replace('tinypng_sizes_', '', $element->getAttribute('id'));
8
  protected static $driver;
9
 
10
  public static function setUpBeforeClass() {
11
+ self::$driver = RemoteWebDriver::createBySessionId($GLOBALS['global_session_id'], $GLOBALS['global_webdriver_host']);
12
  }
13
 
14
  protected function upload_image($path) {
33
  }
34
 
35
  protected function set_api_key($api_key) {
36
+ $url = wordpress('/wp-admin/options-media.php');
37
+ if (self::$driver->getCurrentUrl() != $url) {
38
+ self::$driver->get($url);
39
+ }
40
  self::$driver->findElement(WebDriverBy::name('tinypng_api_key'))->clear()->sendKeys($api_key);
41
  self::$driver->findElement(WebDriverBy::tagName('form'))->submit();
42
  return self::$driver->findElement(WebDriverBy::name('tinypng_api_key'));
43
  }
44
 
45
  protected function enable_compression_sizes($sizes) {
46
+ $url = wordpress('/wp-admin/options-media.php');
47
+ if (self::$driver->getCurrentUrl() != $url) {
48
+ self::$driver->get($url);
49
+ }
50
  $elements = self::$driver->findElements(WebDriverBy::xpath('//input[starts-with(@id, "tinypng_sizes_")]'));
51
  foreach($elements as $element) {
52
  $size = str_replace('tinypng_sizes_', '', $element->getAttribute('id'));
test/integration/SettingsIntegrationTest.php CHANGED
@@ -9,6 +9,10 @@ class SettingsIntegrationTest extends IntegrationTestCase {
9
  self::$driver->get(wordpress('/wp-admin/options-media.php'));
10
  }
11
 
 
 
 
 
12
  public function testTitlePresence()
13
  {
14
  $h3s = self::$driver->findElements(WebDriverBy::tagName('h3'));
@@ -26,6 +30,23 @@ class SettingsIntegrationTest extends IntegrationTestCase {
26
  $this->assertEquals('1234', $element->getAttribute('value'));
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  public function testDefaultSizesBeingCompressed() {
30
  $elements = self::$driver->findElements(
31
  WebDriverBy::xpath('//input[@type="checkbox" and starts-with(@name, "tinypng_sizes") and @checked="checked"]'));
@@ -64,4 +85,20 @@ class SettingsIntegrationTest extends IntegrationTestCase {
64
  WebDriverBy::xpath('//input[@type="checkbox" and starts-with(@name, "tinypng_sizes") and @checked="checked"]'));
65
  $this->assertEquals(0, count(array_map('elementName', $elements)));
66
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
9
  self::$driver->get(wordpress('/wp-admin/options-media.php'));
10
  }
11
 
12
+ public function tearDown() {
13
+ clear_settings();
14
+ }
15
+
16
  public function testTitlePresence()
17
  {
18
  $h3s = self::$driver->findElements(WebDriverBy::tagName('h3'));
30
  $this->assertEquals('1234', $element->getAttribute('value'));
31
  }
32
 
33
+ public function testShouldShowNoticeIfNoApiKeyIsSet() {
34
+ $element = self::$driver->findElement(WebDriverBy::cssSelector('.error a'));
35
+ $this->assertStringEndsWith('options-media.php#tiny-compress-images', $element->getAttribute('href'));
36
+ }
37
+
38
+ public function testShouldShowNoNoticeIfApiKeyIsSet() {
39
+ $this->set_api_key('1234');
40
+ $elements = self::$driver->findElements(WebDriverBy::cssSelector('.error a'));
41
+ $this->assertEquals(0, count($elements));
42
+ }
43
+
44
+ public function testNoApiKeyNoticeShouldLinkToSettings() {
45
+ self::$driver->findElement(WebDriverBy::cssSelector('.error a'))->click();
46
+ $this->assertStringEndsWith('options-media.php#tiny-compress-images', self::$driver->getCurrentURL());
47
+ }
48
+
49
+
50
  public function testDefaultSizesBeingCompressed() {
51
  $elements = self::$driver->findElements(
52
  WebDriverBy::xpath('//input[@type="checkbox" and starts-with(@name, "tinypng_sizes") and @checked="checked"]'));
85
  WebDriverBy::xpath('//input[@type="checkbox" and starts-with(@name, "tinypng_sizes") and @checked="checked"]'));
86
  $this->assertEquals(0, count(array_map('elementName', $elements)));
87
  }
88
+
89
+ public function testStatusPresenceOK() {
90
+ reset_webservice();
91
+ $this->set_api_key('PNG123');
92
+ $elements = self::$driver->findElement(WebDriverBy::id('tiny-compress-status'))->findElements(WebDriverBy::tagName('p'));
93
+ $statuses = array_map('innerText', $elements);
94
+ $this->assertContains('API connection successful', $statuses);
95
+ $this->assertContains('You have made 0 compressions this month.', $statuses);
96
+ }
97
+
98
+ public function testStatusPresenseFail() {
99
+ $this->set_api_key('INVALID123');
100
+ $elements = self::$driver->findElement(WebDriverBy::id('tiny-compress-status'))->findElements(WebDriverBy::tagName('p'));
101
+ $statuses = array_map('innerText', $elements);
102
+ $this->assertContains('API connection unsuccessful', $statuses);
103
+ }
104
  }
test/mock-tinypng-webservice/.htaccess CHANGED
@@ -1,3 +1,4 @@
1
  RewriteEngine On
2
  RewriteRule ^shrink$ shrink.php [last]
3
  RewriteRule ^output/.+$ output.php [last]
 
1
  RewriteEngine On
2
  RewriteRule ^shrink$ shrink.php [last]
3
  RewriteRule ^output/.+$ output.php [last]
4
+ RewriteRule ^reset$ reset.php [last]
test/mock-tinypng-webservice/example-tinyjpg.jpg DELETED
Binary file
test/mock-tinypng-webservice/example-tinypng.png DELETED
Binary file
test/mock-tinypng-webservice/output-example.jpg ADDED
Binary file
test/mock-tinypng-webservice/output-example.png ADDED
Binary file
test/mock-tinypng-webservice/output-large.png ADDED
Binary file
test/mock-tinypng-webservice/output.php CHANGED
@@ -1,25 +1,19 @@
1
  <?php
2
  ob_start();
3
 
4
- if (preg_match('/png$/', $_SERVER['REQUEST_URI'])) {
5
- png_response();
6
- } else if (preg_match('/jpg$/', $_SERVER['REQUEST_URI'])) {
7
- jpg_response();
8
  } else {
9
- header("HTTP/1.1 404 Not Found");
10
  }
11
 
12
- function png_response() {
13
- header('Content-Type: image/png');
14
  header('Content-Disposition: attachment');
15
- readfile('example-tinypng.png');
16
-
17
- }
18
-
19
- function jpg_response() {
20
- header('Content-Type: image/jpg');
21
- header('Content-Disposition: attachment');
22
- readfile('example-tinyjpg.jpg');
23
  }
24
 
25
  ob_end_flush();
1
  <?php
2
  ob_start();
3
 
4
+ if (preg_match('#output/.+[.](png|jpg)$#', $_SERVER['REQUEST_URI'], $match)) {
5
+ $file = str_replace('/', '-', $match[0]);
6
+ $mime = $match[1] == 'jpg' ? 'image/jpeg' : "image/$ext";
 
7
  } else {
8
+ $file = null;
9
  }
10
 
11
+ if ($file && file_exists($file)) {
12
+ header("Content-Type: $mime");
13
  header('Content-Disposition: attachment');
14
+ readfile($file);
15
+ } else {
16
+ header("HTTP/1.1 404 Not Found");
 
 
 
 
 
17
  }
18
 
19
  ob_end_flush();
test/mock-tinypng-webservice/reset.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ define('SESSION_FILE', '/tmp/session.dat');
4
+
5
+ if (file_exists(SESSION_FILE)) {
6
+ unlink(SESSION_FILE);
7
+ }
test/mock-tinypng-webservice/shrink.php CHANGED
@@ -1,26 +1,95 @@
1
  <?php
2
  ob_start();
3
 
 
 
 
 
 
 
 
 
4
  function mock_png_response() {
5
- header("Location: http://webservice/output/2351zxcf2359.png");
6
- header("Content-Type: application/json; charset=utf-8");
7
- header("Compression-Count: 1");
8
 
 
 
 
 
9
  $response = array(
10
- "input" => array("size" => 12345, "type" => "image/png"),
11
- "output" => array("size" => 1234, "type" => "image.png", "ratio" => 0.307)
12
  );
13
  return json_encode($response);
14
  }
15
 
16
  function mock_jpg_response() {
17
- header("Location: http://webservice/output/2351zxcf2359.jpg");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  header("Content-Type: application/json; charset=utf-8");
19
- header("Compression-Count: 1");
20
 
21
  $response = array(
22
- "input" => array("size" => 12345, "type" => "image/jpg"),
23
- "output" => array("size" => 1234, "type" => "image/jpg", "ratio" => 0.307)
24
  );
25
  return json_encode($response);
26
  }
@@ -29,18 +98,27 @@ $request_headers = apache_request_headers();
29
  $basic_auth = base64_decode(str_replace('Basic ', '', $request_headers['Authorization']));
30
  $api_key_elements = explode(':', $basic_auth);
31
  $api_key = $api_key_elements[1];
32
- header('HTTP/1.1 201 Created');
 
33
 
34
  if ($api_key == 'PNG123') {
35
- print_r(mock_png_response());
 
 
 
 
36
  } else if ($api_key == 'JPG123') {
37
- print_r(mock_jpg_response());
 
 
 
 
 
 
38
  } else {
39
- header('HTTP/1.1 401 Unauthorized');
40
- print_r(json_encode(array(
41
- "error" => "Unauthorized",
42
- "message" => "Credentials are invalid"
43
- )));
44
  }
45
 
 
 
46
  ob_end_flush();
1
  <?php
2
  ob_start();
3
 
4
+ define('SESSION_FILE', '/tmp/session.dat');
5
+
6
+ if (file_exists(SESSION_FILE)) {
7
+ $session = unserialize(file_get_contents(SESSION_FILE));
8
+ } else {
9
+ $session = array('Compression-Count' => 0);
10
+ }
11
+
12
  function mock_png_response() {
13
+ global $session;
 
 
14
 
15
+ $session['Compression-Count'] += 1;
16
+ header('HTTP/1.1 201 Created');
17
+ header("Location: http://webservice/output/example.png");
18
+ header("Compression-Count: {$session['Compression-Count']}");
19
  $response = array(
20
+ "input" => array("size" => 161885, "type" => "image/png"),
21
+ "output" => array("size" => 151021, "type" => "image.png", "ratio" => 0.933)
22
  );
23
  return json_encode($response);
24
  }
25
 
26
  function mock_jpg_response() {
27
+ global $session;
28
+
29
+ $session['Compression-Count'] += 1;
30
+ header('HTTP/1.1 201 Created');
31
+ header("Location: http://webservice/output/example.jpg");
32
+ header("Compression-Count: {$session['Compression-Count']}");
33
+
34
+ $response = array(
35
+ "input" => array("size" => 15391, "type" => "image/jpg"),
36
+ "output" => array("size" => 13910, "type" => "image/jpg", "ratio" => 0.904)
37
+ );
38
+ return json_encode($response);
39
+ }
40
+
41
+ function mock_large_response() {
42
+ global $session;
43
+
44
+ $session['Compression-Count'] += 1;
45
+ header('HTTP/1.1 201 Created');
46
+ header("Location: http://webservice/output/large.png");
47
+ header("Compression-Count: {$session['Compression-Count']}");
48
+
49
+ $response = array(
50
+ "input" => array("size" => 80506, "type" => "image/jpg"),
51
+ "output" => array("size" => 70200, "type" => "image/jpg", "ratio" => 0.872)
52
+ );
53
+ return json_encode($response);
54
+ }
55
+
56
+ function mock_invalid_response() {
57
+ global $session;
58
+
59
+ header('HTTP/1.1 401 Unauthorized');
60
+ header("Content-Type: application/json; charset=utf-8");
61
+
62
+ $response = array(
63
+ "error" => "Unauthorized",
64
+ "message" => "Credentials are invalid"
65
+ );
66
+ return json_encode($response);
67
+ }
68
+
69
+ function mock_empty_response() {
70
+ global $session;
71
+
72
+ header('HTTP/1.1 400 Bad Request');
73
+ header("Content-Type: application/json; charset=utf-8");
74
+ header("Compression-Count: {$session['Compression-Count']}");
75
+
76
+ $response = array(
77
+ "error" => "InputMissing",
78
+ "message" => "Your monthly limit has been exceeded"
79
+ );
80
+ return json_encode($response);
81
+ }
82
+
83
+ function mock_limit_reached_response() {
84
+ global $session;
85
+
86
+ header('HTTP/1.1 429 Too Many Requests');
87
  header("Content-Type: application/json; charset=utf-8");
88
+ header("Compression-Count: 500");
89
 
90
  $response = array(
91
+ "error" => "TooManyRequests",
92
+ "message" => "Your monthly limit has been exceeded"
93
  );
94
  return json_encode($response);
95
  }
98
  $basic_auth = base64_decode(str_replace('Basic ', '', $request_headers['Authorization']));
99
  $api_key_elements = explode(':', $basic_auth);
100
  $api_key = $api_key_elements[1];
101
+
102
+ header("Content-Type: application/json; charset=utf-8");
103
 
104
  if ($api_key == 'PNG123') {
105
+ if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
106
+ echo mock_empty_response();
107
+ } else {
108
+ echo mock_png_response();
109
+ }
110
  } else if ($api_key == 'JPG123') {
111
+ if (intval($_SERVER['CONTENT_LENGTH']) == 0) {
112
+ echo mock_empty_response();
113
+ } else {
114
+ echo mock_jpg_response();
115
+ }
116
+ } else if ($api_key == 'LIMIT123') {
117
+ echo mock_limit_reached_response();
118
  } else {
119
+ echo mock_invalid_response();
 
 
 
 
120
  }
121
 
122
+ file_put_contents(SESSION_FILE, serialize($session));
123
+
124
  ob_end_flush();
test/unit/TinyPluginTest.php CHANGED
@@ -2,6 +2,9 @@
2
 
3
  require_once(dirname(__FILE__) . "/TinyTestCase.php");
4
 
 
 
 
5
  class Tiny_Plugin_Test extends TinyTestCase {
6
  public function setUp() {
7
  parent::setUp();
@@ -12,13 +15,38 @@ class Tiny_Plugin_Test extends TinyTestCase {
12
  ->getMock();
13
  $this->subject->set_compressor($this->compressor);
14
 
15
- $this->wp->stub('wp_upload_dir', create_function('', 'return array("basedir" => "/root/wp-content/upload");'));
16
  $this->wp->addOption("tinypng_api_key", "test123");
17
  $this->wp->addOption("tinypng_sizes[0]", "on");
18
  $this->wp->addOption("tinypng_sizes[large]", "on");
19
  $this->wp->addOption("tinypng_sizes[post-thumbnail]", "on");
20
 
21
  $this->wp->addImageSize('post-thumbnail', array('width' => 825, 'height' => 510));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
 
24
  public function testInitShouldAddFilters() {
@@ -32,33 +60,53 @@ class Tiny_Plugin_Test extends TinyTestCase {
32
  public function testCompressShouldRespectSettings() {
33
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
34
  $this->compressor->expects($this->exactly(3))->method('compress_file')->withConsecutive(
35
- array($this->equalTo('/root/wp-content/upload/14/01/test.png')),
36
- array($this->equalTo('/root/wp-content/upload/14/01/test-large.png')),
37
- array($this->equalTo('/root/wp-content/upload/14/01/test-post-thumbnail.png'))
38
- )->will($this->returnCallback('compressTestFile'));
39
- $this->subject->compress_attachment(getTestMetadata(), 1);
40
  }
41
 
42
  public function testCompressShouldNotCompressTwice() {
43
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
44
- $meta = new Tiny_Metadata(1);
45
- $meta->add_response(compressTestFile('test.png'));
46
- $meta->add_response(compressTestFile('test-large.png'), 'large');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  $meta->update();
48
 
 
 
49
  $this->compressor->expects($this->once())->method('compress_file')->withConsecutive(
50
- array($this->equalTo('/root/wp-content/upload/14/01/test-post-thumbnail.png'))
51
- )->will($this->returnCallback('compressTestFile'));
52
- $this->subject->compress_attachment(getTestMetadata(), 1);
53
  }
54
 
55
- public function testCompressShouldUpdateMetaData() {
56
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
57
  $this->compressor->expects($this->exactly(3))->method('compress_file')->will(
58
- $this->returnCallback('compressTestFile')
59
  );
60
 
61
- $this->subject->compress_attachment(getTestMetadata(), 1);
62
 
63
  $metadata = $this->wp->getMetadata(1, 'tiny_compress_images', true);
64
  foreach ($metadata as $key => $values) {
@@ -79,7 +127,7 @@ class Tiny_Plugin_Test extends TinyTestCase {
79
  $this->throwException(new Tiny_Exception('Does not appear to be a PNG or JPEG file', 'BadSignature'))
80
  );
81
 
82
- $this->subject->compress_attachment(getTestMetadata(), 1);
83
 
84
  $metadata = $this->wp->getMetadata(1, 'tiny_compress_images', true);
85
  foreach ($metadata as $key => $values) {
@@ -98,13 +146,38 @@ class Tiny_Plugin_Test extends TinyTestCase {
98
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
99
  $this->compressor->expects($this->never())->method('compress_file');
100
 
101
- $this->subject->compress_attachment(getTestMetadata(), 1);
102
  }
103
 
104
  public function testShouldReturnIfNoImage() {
105
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "video/webm";'));
106
  $this->compressor->expects($this->never())->method('compress_file');
107
 
108
- $this->subject->compress_attachment(getTestMetadata(), 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
110
  }
2
 
3
  require_once(dirname(__FILE__) . "/TinyTestCase.php");
4
 
5
+ use org\bovigo\vfs\vfsStream;
6
+ use org\bovigo\vfs\content\LargeFileContent;
7
+
8
  class Tiny_Plugin_Test extends TinyTestCase {
9
  public function setUp() {
10
  parent::setUp();
15
  ->getMock();
16
  $this->subject->set_compressor($this->compressor);
17
 
 
18
  $this->wp->addOption("tinypng_api_key", "test123");
19
  $this->wp->addOption("tinypng_sizes[0]", "on");
20
  $this->wp->addOption("tinypng_sizes[large]", "on");
21
  $this->wp->addOption("tinypng_sizes[post-thumbnail]", "on");
22
 
23
  $this->wp->addImageSize('post-thumbnail', array('width' => 825, 'height' => 510));
24
+ $this->wp->createImages();
25
+ }
26
+
27
+ public function successCompress($file) {
28
+ if (preg_match('#[^-]+-([^.]+)[.](png|jpe?g)$#', basename($file), $match)) {
29
+ $key = $match[1];
30
+ } else {
31
+ $key = null;
32
+ }
33
+
34
+ $input = filesize($file);
35
+ switch ($key) {
36
+ case "thumbnail":
37
+ $output = 81; break;
38
+ case "medium":
39
+ $output = 768; break;
40
+ case "large":
41
+ $output = 6789; break;
42
+ case "post-thumbnail":
43
+ $output = 1000; break;
44
+ default:
45
+ $output = 10000;
46
+ }
47
+ $this->vfs->getChild(vfsStream::path($file))->truncate($output);
48
+ return array('input' => array('size' => $input), 'output' => array('size' => $output));
49
+
50
  }
51
 
52
  public function testInitShouldAddFilters() {
60
  public function testCompressShouldRespectSettings() {
61
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
62
  $this->compressor->expects($this->exactly(3))->method('compress_file')->withConsecutive(
63
+ array($this->equalTo('vfs://root/wp-content/uploads/14/01/test.png')),
64
+ array($this->equalTo('vfs://root/wp-content/uploads/14/01/test-large.png')),
65
+ array($this->equalTo('vfs://root/wp-content/uploads/14/01/test-post-thumbnail.png'))
66
+ )->will($this->returnCallback(array($this, 'successCompress')));
67
+ $this->subject->compress_attachment($this->wp->getTestMetadata(), 1);
68
  }
69
 
70
  public function testCompressShouldNotCompressTwice() {
71
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
72
+
73
+ $testmeta = $this->wp->getTestMetadata();
74
+ $meta = new Tiny_Metadata(1, $testmeta);
75
+ $meta->add_response(self::successCompress('vfs://root/wp-content/uploads/14/01/test.png'));
76
+ $meta->add_response(self::successCompress('vfs://root/wp-content/uploads/14/01/test-large.png'), 'large');
77
+ $meta->update();
78
+
79
+ $this->compressor->expects($this->once())->method('compress_file')->withConsecutive(
80
+ array($this->equalTo('vfs://root/wp-content/uploads/14/01/test-post-thumbnail.png'))
81
+ )->will($this->returnCallback(array($this, 'successCompress')));
82
+ $this->subject->compress_attachment($testmeta, 1);
83
+ }
84
+
85
+ public function testCompressWhenFileChanged() {
86
+ $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
87
+
88
+ $testmeta = $this->wp->getTestMetadata();
89
+ $meta = new Tiny_Metadata(1, $testmeta);
90
+ $meta->add_response(self::successCompress('vfs://root/wp-content/uploads/14/01/test.png'));
91
+ $meta->add_response(self::successCompress('vfs://root/wp-content/uploads/14/01/test-large.png'), 'large');
92
+ $meta->add_response(self::successCompress('vfs://root/wp-content/uploads/14/01/test-post-thumbnail.png'), 'post-thumbnail');
93
  $meta->update();
94
 
95
+ $this->vfs->getChild('wp-content/uploads/14/01/test-large.png')->truncate(100000);
96
+
97
  $this->compressor->expects($this->once())->method('compress_file')->withConsecutive(
98
+ array($this->equalTo('vfs://root/wp-content/uploads/14/01/test-large.png'))
99
+ )->will($this->returnCallback(array($this, 'successCompress')));
100
+ $this->subject->compress_attachment($testmeta, 1);
101
  }
102
 
103
+ public function testCompressShouldUpdateMetadata() {
104
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
105
  $this->compressor->expects($this->exactly(3))->method('compress_file')->will(
106
+ $this->returnCallback(array($this, 'successCompress'))
107
  );
108
 
109
+ $this->subject->compress_attachment($this->wp->getTestMetadata(), 1);
110
 
111
  $metadata = $this->wp->getMetadata(1, 'tiny_compress_images', true);
112
  foreach ($metadata as $key => $values) {
127
  $this->throwException(new Tiny_Exception('Does not appear to be a PNG or JPEG file', 'BadSignature'))
128
  );
129
 
130
+ $this->subject->compress_attachment($this->wp->getTestMetadata(), 1);
131
 
132
  $metadata = $this->wp->getMetadata(1, 'tiny_compress_images', true);
133
  foreach ($metadata as $key => $values) {
146
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
147
  $this->compressor->expects($this->never())->method('compress_file');
148
 
149
+ $this->subject->compress_attachment($this->wp->getTestMetadata(), 1);
150
  }
151
 
152
  public function testShouldReturnIfNoImage() {
153
  $this->wp->stub('get_post_mime_type', create_function('$i', 'return "video/webm";'));
154
  $this->compressor->expects($this->never())->method('compress_file');
155
 
156
+ $this->subject->compress_attachment($this->wp->getTestMetadata(), 1);
157
+ }
158
+
159
+ public function testWrongMetadataShouldNotShowWarnings() {
160
+ $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
161
+ $this->compressor->expects($this->exactly(1))->method('compress_file')->will(
162
+ $this->returnCallback(array($this, 'successCompress'))
163
+ );
164
+
165
+ $testmeta = $this->wp->getTestMetadata();
166
+ $testmeta['sizes'] = 0;
167
+
168
+ $this->subject->compress_attachment($testmeta, 1);
169
+ }
170
+
171
+ public function testWrongMetadataShouldSaveTinyMetadata() {
172
+ $this->wp->stub('get_post_mime_type', create_function('$i', 'return "image/png";'));
173
+ $this->compressor->expects($this->exactly(1))->method('compress_file')->will(
174
+ $this->returnCallback(array($this, 'successCompress'))
175
+ );
176
+
177
+ $testmeta = $this->wp->getTestMetadata();
178
+ $testmeta['sizes'] = 0;
179
+
180
+ $this->subject->compress_attachment($testmeta, 1);
181
+ $this->assertEquals(1, count($this->wp->getCalls('update_post_meta')));
182
  }
183
  }
test/unit/TinySettingsTest.php CHANGED
@@ -14,6 +14,7 @@ class Tiny_Settings_Test extends TinyTestCase {
14
  $this->assertEquals(array(
15
  array('media', 'tinypng_api_key'),
16
  array('media', 'tinypng_sizes'),
 
17
  ), $this->wp->getCalls('register_setting'));
18
  }
19
 
@@ -27,6 +28,7 @@ class Tiny_Settings_Test extends TinyTestCase {
27
  $this->assertEquals(array(
28
  array('tinypng_api_key', 'TinyPNG API key', array($this->subject, 'render_api_key'), 'media', 'tinypng_settings', array('label_for' => 'tinypng_api_key')),
29
  array('tinypng_sizes', 'File compression', array($this->subject, 'render_sizes'), 'media', 'tinypng_settings'),
 
30
  ), $this->wp->getCalls('add_settings_field'));
31
  }
32
 
@@ -84,4 +86,4 @@ class Tiny_Settings_Test extends TinyTestCase {
84
  'large' => array('width' => 1024, 'height' => 1024, 'tinify' => true),
85
  ), $this->subject->get_sizes());
86
  }
87
- }
14
  $this->assertEquals(array(
15
  array('media', 'tinypng_api_key'),
16
  array('media', 'tinypng_sizes'),
17
+ array('media', 'tinypng_status')
18
  ), $this->wp->getCalls('register_setting'));
19
  }
20
 
28
  $this->assertEquals(array(
29
  array('tinypng_api_key', 'TinyPNG API key', array($this->subject, 'render_api_key'), 'media', 'tinypng_settings', array('label_for' => 'tinypng_api_key')),
30
  array('tinypng_sizes', 'File compression', array($this->subject, 'render_sizes'), 'media', 'tinypng_settings'),
31
+ array('tinypng_status', 'Connection status', array($this->subject, 'render_pending_status'), 'media', 'tinypng_settings')
32
  ), $this->wp->getCalls('add_settings_field'));
33
  }
34
 
86
  'large' => array('width' => 1024, 'height' => 1024, 'tinify' => true),
87
  ), $this->subject->get_sizes());
88
  }
89
+ }
test/unit/TinyTestCase.php CHANGED
@@ -1,9 +1,10 @@
1
  <?php
2
 
3
  require 'vendor/autoload.php';
4
- require(dirname(__FILE__) . '/../helpers/compress.php');
5
  require(dirname(__FILE__) . '/../helpers/wordpress.php');
6
 
 
 
7
  function plugin_autoloader($class) {
8
  $file = dirname(__FILE__) . '/../../src/class-' . str_replace('_', '-', strtolower($class)) . '.php';
9
  if (file_exists($file)) {
@@ -17,12 +18,13 @@ spl_autoload_register('plugin_autoloader');
17
 
18
  abstract class TinyTestCase extends PHPUnit_Framework_TestCase {
19
  protected $wp;
 
20
 
21
  protected function setUp() {
22
- $this->wp = $GLOBALS['wp'];
 
23
  }
24
 
25
  protected function tearDown() {
26
- $this->wp->clear();
27
  }
28
  }
1
  <?php
2
 
3
  require 'vendor/autoload.php';
 
4
  require(dirname(__FILE__) . '/../helpers/wordpress.php');
5
 
6
+ use org\bovigo\vfs\vfsStream;
7
+
8
  function plugin_autoloader($class) {
9
  $file = dirname(__FILE__) . '/../../src/class-' . str_replace('_', '-', strtolower($class)) . '.php';
10
  if (file_exists($file)) {
18
 
19
  abstract class TinyTestCase extends PHPUnit_Framework_TestCase {
20
  protected $wp;
21
+ protected $vfs;
22
 
23
  protected function setUp() {
24
+ $this->vfs = vfsStream::setup();
25
+ $this->wp = new WordPressStubs($this->vfs);
26
  }
27
 
28
  protected function tearDown() {
 
29
  }
30
  }
tiny-compress-images.php CHANGED
@@ -2,13 +2,14 @@
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
- * Version: 1.1.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * License: GPLv2 or later
9
  */
10
 
11
 
 
12
  require (dirname(__FILE__) . '/src/class-tiny-php.php');
13
  require (dirname(__FILE__) . '/src/class-tiny-wp-base.php');
14
  require (dirname(__FILE__) . '/src/class-tiny-exception.php');
@@ -18,5 +19,10 @@ require (dirname(__FILE__) . '/src/class-tiny-compress-fopen.php');
18
  require (dirname(__FILE__) . '/src/class-tiny-metadata.php');
19
  require (dirname(__FILE__) . '/src/class-tiny-settings.php');
20
  require (dirname(__FILE__) . '/src/class-tiny-plugin.php');
 
21
 
22
  $tiny_plugin = new Tiny_Plugin();
 
 
 
 
2
  /**
3
  * Plugin Name: Compress JPEG & PNG images
4
  * Description: Speed up your website. Optimize your JPEG and PNG images automatically with TinyPNG.
5
+ * Version: 1.3.0
6
  * Author: TinyPNG
7
  * Author URI: https://tinypng.com
8
  * License: GPLv2 or later
9
  */
10
 
11
 
12
+ require (dirname(__FILE__) . '/src/config/tiny-config.php');
13
  require (dirname(__FILE__) . '/src/class-tiny-php.php');
14
  require (dirname(__FILE__) . '/src/class-tiny-wp-base.php');
15
  require (dirname(__FILE__) . '/src/class-tiny-exception.php');
19
  require (dirname(__FILE__) . '/src/class-tiny-metadata.php');
20
  require (dirname(__FILE__) . '/src/class-tiny-settings.php');
21
  require (dirname(__FILE__) . '/src/class-tiny-plugin.php');
22
+ require (dirname(__FILE__) . '/src/class-tiny-notices.php');
23
 
24
  $tiny_plugin = new Tiny_Plugin();
25
+
26
+ if (!defined('TINY_DEBUG')) {
27
+ define('TINY_DEBUG', null);
28
+ }