PluginProbe
Core Rollback / trunk
Core Rollback vtrunk
1.4.3 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.4.0 1.4.1 1.4.2
core-rollback / src / Core.php

Core.php in Core Rollback trunk, at src/Core.php

199 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Core Rollback
4 *
5 * @author Andy Fragen
6 * @license MIT
7 * @link https://github.com/afragen/core-rollback
8 * @package core-rollback
9 */
10
11 namespace Fragen\Rollback;
12
13 use stdClass;
14
15 /*
16 * Exit if called directly.
17 */
18 if ( ! defined( 'WPINC' ) ) {
19 die;
20 }
21
22 /**
23 * Class Core
24 */
25 class Core {
26 /**
27 * Core versions for re-installation.
28 *
29 * @var array
30 */
31 public static $core_versions;
32
33 /**
34 * Constructor.
35 */
36 public function __construct() {
37 static::$core_versions = $this->get_core_versions();
38 }
39
40 /**
41 * Get all core versions from Core API.
42 *
43 * @return array Array of versions and downloads.
44 */
45 public function get_core_versions() {
46 $versions = get_site_transient( 'core_rollback' );
47 if ( ! $versions ) {
48 $versions = [];
49 $locale = get_locale();
50 $response = wp_remote_get( "https://api.wordpress.org/core/version-check/1.7/?locale={$locale}" );
51 if ( is_wp_error( $response ) ) {
52 return [];
53 }
54 $body = wp_remote_retrieve_body( $response );
55 $body = json_decode( $body );
56 $offers = isset( $body->offers ) ? $body->offers : [];
57 foreach ( $offers as $offer ) {
58 if ( version_compare( $offer->version, '4.0', '>=' ) ) {
59 $offer->response = 'latest';
60 $versions[ $offer->version ] = $offer;
61 }
62 }
63 if ( ! empty( $versions ) ) {
64 set_site_transient( 'core_rollback', $versions, DAY_IN_SECONDS );
65 }
66 }
67
68 return $versions;
69 }
70
71 /**
72 * Load hooks.
73 */
74 public function load_hooks() {
75 add_filter( 'http_request_args', [ $this, 'filter_http_request_args' ], 10, 2 );
76 add_filter( 'pre_http_request', [ $this, 'filter_http_request' ], 10, 3 );
77 add_filter( 'site_transient_update_core', [ $this, 'add_rollback_offer' ], 10, 1 );
78 }
79
80 /**
81 * Add core rollback version to http_request_args.
82 *
83 * @param array $args Array of HTTP request args.
84 * @param string $url URL for HTTP request.
85 *
86 * @return array
87 */
88 public function filter_http_request_args( $args, $url ) {
89 if ( false === strpos( $url, '//api.wordpress.org/core/version-check/' ) ) {
90 return $args;
91 }
92 $rollback = get_site_transient( '_core_rollback' );
93
94 if ( $rollback ) {
95 $args['_rollback_version'] = $rollback['core_dropdown'];
96 }
97
98 return $args;
99 }
100
101 /**
102 * Filter 'pre_http_request' to add rollback API check.
103 *
104 * @param mixed $result $result from filter.
105 * @param array $args Array of filter args.
106 * @param string $url URL from filter.
107 *
108 * @return stdClass $response Output from wp_remote_get().
109 */
110 public function filter_http_request( $result, $args, $url ) {
111 if ( $result || isset( $args['_core_rollback'] ) || ! isset( $args['_rollback_version'] ) ) {
112 return $result;
113 }
114 if ( false === strpos( $url, '//api.wordpress.org/core/version-check/' ) ) {
115 return $result;
116 }
117
118 // It's a core-update request.
119 $args['_core_rollback'] = true;
120
121 $response = wp_remote_get( $url, $args );
122 if ( is_wp_error( $response ) ) {
123 return $result;
124 }
125 if ( isset( $args['_rollback_version'] ) ) {
126 $rollback_version = sanitize_text_field( $args['_rollback_version'] );
127 $response = $this->set_rollback( $response, $rollback_version );
128 }
129
130 return $response;
131 }
132
133 /**
134 * Update Core API update response to add rollback.
135 *
136 * @param stdClass $response Core API response.
137 * @param string $rollback_version Rollback version.
138 *
139 * @return stdClass
140 */
141 public function set_rollback( $response, $rollback_version ) {
142 if ( ! array_key_exists( $rollback_version, static::$core_versions ) ) {
143 return $response;
144 }
145 $body = wp_remote_retrieve_body( $response );
146 $offers = json_decode( $body );
147 $latest = false;
148 $num = count( array_keys( $offers->offers ) );
149 foreach ( array_keys( $offers->offers ) as $key ) {
150 if ( 0 === $key ) {
151 continue;
152 }
153
154 if ( 'latest' === $offers->offers[ $key ]->response ) {
155 $offers->offers[ $key ] = static::$core_versions[ $rollback_version ];
156 $latest = true;
157 }
158 }
159
160 if ( ! $latest && ( ( $key + 1 ) === $num ) ) {
161 $offers->offers[ $num ] = static::$core_versions[ $rollback_version ];
162 }
163 set_site_transient( '_core_rollback_offers', $offers->offers, 15 );
164
165 $body = json_encode( $offers );
166 $response['body'] = $body;
167
168 return $response;
169 }
170
171 /**
172 * Add core rollback offer to update_core transient.
173 *
174 * @param stdClass $transient Update core transient.
175 *
176 * @return stdClass
177 */
178 public function add_rollback_offer( $transient ) {
179 if ( ! $transient ) {
180 $transient = new stdClass();
181 $transient->last_checked = time();
182 $transient->version_checked = function_exists( 'wp_get_wp_version' ) ? wp_get_wp_version() : get_bloginfo( 'version' );
183 $transient->updates = [];
184 }
185 $rollback = get_site_transient( '_core_rollback' );
186 $version = isset( $rollback['core_dropdown'] ) ? $rollback['core_dropdown'] : '';
187 $offers = get_site_transient( '_core_rollback_offers' );
188 $versions = $this->get_core_versions();
189 if ( ! empty( $versions ) && array_keys( $versions )[0] === $version ) {
190 unset( $transient->updates[1] );
191 }
192 if ( $offers && 'latest' === $offers[1]->response && $version === $offers[1]->version ) {
193 $transient->updates[] = $offers[1];
194 }
195
196 return $transient;
197 }
198 }
199