Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/woocomme.../src/Admin/RemoteSp...
File: DataSourcePoller.php
<?php
[0] Fix | Delete
[1] Fix | Delete
namespace Automattic\WooCommerce\Admin\RemoteSpecs;
[2] Fix | Delete
[3] Fix | Delete
/**
[4] Fix | Delete
* Specs data source poller class.
[5] Fix | Delete
* This handles polling specs from JSON endpoints, and
[6] Fix | Delete
* stores the specs in to the database as an option.
[7] Fix | Delete
*/
[8] Fix | Delete
abstract class DataSourcePoller {
[9] Fix | Delete
[10] Fix | Delete
/**
[11] Fix | Delete
* Get class instance.
[12] Fix | Delete
*/
[13] Fix | Delete
abstract public static function get_instance();
[14] Fix | Delete
[15] Fix | Delete
/**
[16] Fix | Delete
* Name of data sources filter.
[17] Fix | Delete
*/
[18] Fix | Delete
const FILTER_NAME = 'data_source_poller_data_sources';
[19] Fix | Delete
[20] Fix | Delete
/**
[21] Fix | Delete
* Name of data source specs filter.
[22] Fix | Delete
*/
[23] Fix | Delete
const FILTER_NAME_SPECS = 'data_source_poller_specs';
[24] Fix | Delete
[25] Fix | Delete
/**
[26] Fix | Delete
* Id of DataSourcePoller.
[27] Fix | Delete
*
[28] Fix | Delete
* @var string
[29] Fix | Delete
*/
[30] Fix | Delete
protected $id = array();
[31] Fix | Delete
[32] Fix | Delete
/**
[33] Fix | Delete
* Default data sources array.
[34] Fix | Delete
*
[35] Fix | Delete
* @var array
[36] Fix | Delete
*/
[37] Fix | Delete
protected $data_sources = array();
[38] Fix | Delete
[39] Fix | Delete
/**
[40] Fix | Delete
* Default args.
[41] Fix | Delete
*
[42] Fix | Delete
* @var array
[43] Fix | Delete
*/
[44] Fix | Delete
protected $args = array();
[45] Fix | Delete
[46] Fix | Delete
/**
[47] Fix | Delete
* The logger instance.
[48] Fix | Delete
*
[49] Fix | Delete
* @var WC_Logger|null
[50] Fix | Delete
*/
[51] Fix | Delete
protected static $logger = null;
[52] Fix | Delete
[53] Fix | Delete
/**
[54] Fix | Delete
* Constructor.
[55] Fix | Delete
*
[56] Fix | Delete
* @param string $id id of DataSourcePoller.
[57] Fix | Delete
* @param array $data_sources urls for data sources.
[58] Fix | Delete
* @param array $args Options for DataSourcePoller.
[59] Fix | Delete
*/
[60] Fix | Delete
public function __construct( $id, $data_sources = array(), $args = array() ) {
[61] Fix | Delete
$this->data_sources = $data_sources;
[62] Fix | Delete
$this->id = $id;
[63] Fix | Delete
[64] Fix | Delete
$arg_defaults = array(
[65] Fix | Delete
'spec_key' => 'id',
[66] Fix | Delete
'transient_name' => 'woocommerce_admin_' . $id . '_specs',
[67] Fix | Delete
'transient_expiry' => 7 * DAY_IN_SECONDS,
[68] Fix | Delete
);
[69] Fix | Delete
$this->args = wp_parse_args( $args, $arg_defaults );
[70] Fix | Delete
}
[71] Fix | Delete
[72] Fix | Delete
/**
[73] Fix | Delete
* Get the logger instance.
[74] Fix | Delete
*
[75] Fix | Delete
* @return WC_Logger
[76] Fix | Delete
*/
[77] Fix | Delete
protected static function get_logger() {
[78] Fix | Delete
if ( is_null( self::$logger ) ) {
[79] Fix | Delete
self::$logger = wc_get_logger();
[80] Fix | Delete
}
[81] Fix | Delete
[82] Fix | Delete
return self::$logger;
[83] Fix | Delete
}
[84] Fix | Delete
[85] Fix | Delete
/**
[86] Fix | Delete
* Returns the key identifier of spec, this can easily be overwritten. Defaults to id.
[87] Fix | Delete
*
[88] Fix | Delete
* @param mixed $spec a JSON parsed spec coming from the JSON feed.
[89] Fix | Delete
* @return string|boolean
[90] Fix | Delete
*/
[91] Fix | Delete
protected function get_spec_key( $spec ) {
[92] Fix | Delete
$key = $this->args['spec_key'];
[93] Fix | Delete
if ( isset( $spec->$key ) ) {
[94] Fix | Delete
return $spec->$key;
[95] Fix | Delete
}
[96] Fix | Delete
return false;
[97] Fix | Delete
}
[98] Fix | Delete
[99] Fix | Delete
/**
[100] Fix | Delete
* Reads the data sources for specs and persists those specs.
[101] Fix | Delete
*
[102] Fix | Delete
* @return array list of specs.
[103] Fix | Delete
*/
[104] Fix | Delete
public function get_specs_from_data_sources() {
[105] Fix | Delete
$locale = get_user_locale();
[106] Fix | Delete
$specs_group = get_transient( $this->args['transient_name'] ) ?? array();
[107] Fix | Delete
$specs = isset( $specs_group[ $locale ] ) ? $specs_group[ $locale ] : null;
[108] Fix | Delete
[109] Fix | Delete
if ( ! is_array( $specs ) ) {
[110] Fix | Delete
$this->read_specs_from_data_sources();
[111] Fix | Delete
$specs_group = get_transient( $this->args['transient_name'] );
[112] Fix | Delete
$specs = isset( $specs_group[ $locale ] ) ? $specs_group[ $locale ] : array();
[113] Fix | Delete
}
[114] Fix | Delete
[115] Fix | Delete
/**
[116] Fix | Delete
* Filter specs.
[117] Fix | Delete
*
[118] Fix | Delete
* @param array $specs List of specs.
[119] Fix | Delete
* @param string $this->id Spec identifier.
[120] Fix | Delete
*
[121] Fix | Delete
* @since 8.8.0
[122] Fix | Delete
*/
[123] Fix | Delete
$specs = apply_filters( self::FILTER_NAME_SPECS, $specs, $this->id );
[124] Fix | Delete
return false !== $specs ? $specs : array();
[125] Fix | Delete
}
[126] Fix | Delete
[127] Fix | Delete
/**
[128] Fix | Delete
* Gets specs from cache if it exists.
[129] Fix | Delete
*
[130] Fix | Delete
* @return array list of specs.
[131] Fix | Delete
*/
[132] Fix | Delete
public function get_cached_specs() {
[133] Fix | Delete
$locale = get_user_locale();
[134] Fix | Delete
$specs_group = get_transient( $this->args['transient_name'] ) ?? array();
[135] Fix | Delete
$specs = isset( $specs_group[ $locale ] ) ? $specs_group[ $locale ] : null;
[136] Fix | Delete
[137] Fix | Delete
/**
[138] Fix | Delete
* Filter specs.
[139] Fix | Delete
*
[140] Fix | Delete
* @param array $specs List of specs.
[141] Fix | Delete
* @param string $this->id Spec identifier.
[142] Fix | Delete
*
[143] Fix | Delete
* @since 8.8.0
[144] Fix | Delete
*/
[145] Fix | Delete
$specs = apply_filters( self::FILTER_NAME_SPECS, $specs, $this->id );
[146] Fix | Delete
[147] Fix | Delete
return false !== $specs ? $specs : array();
[148] Fix | Delete
}
[149] Fix | Delete
[150] Fix | Delete
/**
[151] Fix | Delete
* Reads the data sources for specs and persists those specs.
[152] Fix | Delete
*
[153] Fix | Delete
* @return bool Whether any specs were read.
[154] Fix | Delete
*/
[155] Fix | Delete
public function read_specs_from_data_sources() {
[156] Fix | Delete
$specs = array();
[157] Fix | Delete
[158] Fix | Delete
/**
[159] Fix | Delete
* Filter data sources.
[160] Fix | Delete
*
[161] Fix | Delete
* @param array $this->data_sources List of data sources.
[162] Fix | Delete
* @param string $this->id Spec identifier.
[163] Fix | Delete
*
[164] Fix | Delete
* @since 8.8.0
[165] Fix | Delete
*/
[166] Fix | Delete
$data_sources = apply_filters( self::FILTER_NAME, $this->data_sources, $this->id );
[167] Fix | Delete
[168] Fix | Delete
// Note that this merges the specs from the data sources based on the
[169] Fix | Delete
// id - last one wins.
[170] Fix | Delete
foreach ( $data_sources as $url ) {
[171] Fix | Delete
$specs_from_data_source = self::read_data_source( $url );
[172] Fix | Delete
$this->merge_specs( $specs_from_data_source, $specs, $url );
[173] Fix | Delete
}
[174] Fix | Delete
[175] Fix | Delete
$specs_group = get_transient( $this->args['transient_name'] );
[176] Fix | Delete
$specs_group = is_array( $specs_group ) ? $specs_group : array();
[177] Fix | Delete
$locale = get_user_locale();
[178] Fix | Delete
$specs_group[ $locale ] = $specs;
[179] Fix | Delete
// Persist the specs as a transient.
[180] Fix | Delete
$this->set_specs_transient(
[181] Fix | Delete
$specs_group,
[182] Fix | Delete
$this->args['transient_expiry']
[183] Fix | Delete
);
[184] Fix | Delete
return count( $specs ) !== 0;
[185] Fix | Delete
}
[186] Fix | Delete
[187] Fix | Delete
/**
[188] Fix | Delete
* Delete the specs transient.
[189] Fix | Delete
*
[190] Fix | Delete
* @return bool success of failure of transient deletion.
[191] Fix | Delete
*/
[192] Fix | Delete
public function delete_specs_transient() {
[193] Fix | Delete
return delete_transient( $this->args['transient_name'] );
[194] Fix | Delete
}
[195] Fix | Delete
[196] Fix | Delete
/**
[197] Fix | Delete
* Set the specs transient.
[198] Fix | Delete
*
[199] Fix | Delete
* @param array $specs The specs to set in the transient.
[200] Fix | Delete
* @param int $expiration The expiration time for the transient.
[201] Fix | Delete
*/
[202] Fix | Delete
public function set_specs_transient( $specs, $expiration = 0 ) {
[203] Fix | Delete
set_transient(
[204] Fix | Delete
$this->args['transient_name'],
[205] Fix | Delete
$specs,
[206] Fix | Delete
$expiration,
[207] Fix | Delete
);
[208] Fix | Delete
}
[209] Fix | Delete
[210] Fix | Delete
/**
[211] Fix | Delete
* Read a single data source and return the read specs
[212] Fix | Delete
*
[213] Fix | Delete
* @param string $url The URL to read the specs from.
[214] Fix | Delete
*
[215] Fix | Delete
* @return array The specs that have been read from the data source.
[216] Fix | Delete
*/
[217] Fix | Delete
protected static function read_data_source( $url ) {
[218] Fix | Delete
$logger_context = array( 'source' => $url );
[219] Fix | Delete
$logger = self::get_logger();
[220] Fix | Delete
$response = wp_remote_get(
[221] Fix | Delete
add_query_arg(
[222] Fix | Delete
'locale',
[223] Fix | Delete
get_user_locale(),
[224] Fix | Delete
$url
[225] Fix | Delete
),
[226] Fix | Delete
array(
[227] Fix | Delete
'user-agent' => 'WooCommerce/' . WC_VERSION . '; ' . home_url( '/' ),
[228] Fix | Delete
)
[229] Fix | Delete
);
[230] Fix | Delete
[231] Fix | Delete
if ( is_wp_error( $response ) || ! isset( $response['body'] ) ) {
[232] Fix | Delete
$logger->error(
[233] Fix | Delete
'Error getting data feed',
[234] Fix | Delete
$logger_context
[235] Fix | Delete
);
[236] Fix | Delete
// phpcs:ignore
[237] Fix | Delete
$logger->error( print_r( $response, true ), $logger_context );
[238] Fix | Delete
[239] Fix | Delete
return array();
[240] Fix | Delete
}
[241] Fix | Delete
[242] Fix | Delete
$body = $response['body'];
[243] Fix | Delete
$specs = json_decode( $body );
[244] Fix | Delete
[245] Fix | Delete
if ( null === $specs ) {
[246] Fix | Delete
$logger->error(
[247] Fix | Delete
'Empty response in data feed',
[248] Fix | Delete
$logger_context
[249] Fix | Delete
);
[250] Fix | Delete
[251] Fix | Delete
return array();
[252] Fix | Delete
}
[253] Fix | Delete
[254] Fix | Delete
if ( ! is_array( $specs ) ) {
[255] Fix | Delete
$logger->error(
[256] Fix | Delete
'Data feed is not an array',
[257] Fix | Delete
$logger_context
[258] Fix | Delete
);
[259] Fix | Delete
[260] Fix | Delete
return array();
[261] Fix | Delete
}
[262] Fix | Delete
[263] Fix | Delete
return $specs;
[264] Fix | Delete
}
[265] Fix | Delete
[266] Fix | Delete
/**
[267] Fix | Delete
* Merge the specs.
[268] Fix | Delete
*
[269] Fix | Delete
* @param Array $specs_to_merge_in The specs to merge in to $specs.
[270] Fix | Delete
* @param Array $specs The list of specs being merged into.
[271] Fix | Delete
* @param string $url The url of the feed being merged in (for error reporting).
[272] Fix | Delete
*/
[273] Fix | Delete
protected function merge_specs( $specs_to_merge_in, &$specs, $url ) {
[274] Fix | Delete
foreach ( $specs_to_merge_in as $spec ) {
[275] Fix | Delete
if ( ! $this->validate_spec( $spec, $url ) ) {
[276] Fix | Delete
continue;
[277] Fix | Delete
}
[278] Fix | Delete
[279] Fix | Delete
$id = $this->get_spec_key( $spec );
[280] Fix | Delete
$specs[ $id ] = $spec;
[281] Fix | Delete
}
[282] Fix | Delete
}
[283] Fix | Delete
[284] Fix | Delete
/**
[285] Fix | Delete
* Validate the spec.
[286] Fix | Delete
*
[287] Fix | Delete
* @param object $spec The spec to validate.
[288] Fix | Delete
* @param string $url The url of the feed that provided the spec.
[289] Fix | Delete
*
[290] Fix | Delete
* @return bool The result of the validation.
[291] Fix | Delete
*/
[292] Fix | Delete
protected function validate_spec( $spec, $url ) {
[293] Fix | Delete
$logger = self::get_logger();
[294] Fix | Delete
$logger_context = array( 'source' => $url );
[295] Fix | Delete
[296] Fix | Delete
if ( ! $this->get_spec_key( $spec ) ) {
[297] Fix | Delete
$logger->error(
[298] Fix | Delete
'Spec is invalid because the id is missing in feed',
[299] Fix | Delete
$logger_context
[300] Fix | Delete
);
[301] Fix | Delete
// phpcs:ignore
[302] Fix | Delete
$logger->error( print_r( $spec, true ), $logger_context );
[303] Fix | Delete
[304] Fix | Delete
return false;
[305] Fix | Delete
}
[306] Fix | Delete
[307] Fix | Delete
return true;
[308] Fix | Delete
}
[309] Fix | Delete
}
[310] Fix | Delete
[311] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function