HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/Utility.tar
CaseInsensitiveDictionary.php000064400000004713151535671430012416 0ustar00<?php
/**
 * Case-insensitive dictionary, suitable for HTTP headers
 *
 * @package Requests\Utilities
 */

namespace WpOrg\Requests\Utility;

use ArrayAccess;
use ArrayIterator;
use IteratorAggregate;
use ReturnTypeWillChange;
use WpOrg\Requests\Exception;

/**
 * Case-insensitive dictionary, suitable for HTTP headers
 *
 * @package Requests\Utilities
 */
class CaseInsensitiveDictionary implements ArrayAccess, IteratorAggregate {
	/**
	 * Actual item data
	 *
	 * @var array
	 */
	protected $data = [];

	/**
	 * Creates a case insensitive dictionary.
	 *
	 * @param array $data Dictionary/map to convert to case-insensitive
	 */
	public function __construct(array $data = []) {
		foreach ($data as $offset => $value) {
			$this->offsetSet($offset, $value);
		}
	}

	/**
	 * Check if the given item exists
	 *
	 * @param string $offset Item key
	 * @return boolean Does the item exist?
	 */
	#[ReturnTypeWillChange]
	public function offsetExists($offset) {
		if (is_string($offset)) {
			$offset = strtolower($offset);
		}

		return isset($this->data[$offset]);
	}

	/**
	 * Get the value for the item
	 *
	 * @param string $offset Item key
	 * @return string|null Item value (null if the item key doesn't exist)
	 */
	#[ReturnTypeWillChange]
	public function offsetGet($offset) {
		if (is_string($offset)) {
			$offset = strtolower($offset);
		}

		if (!isset($this->data[$offset])) {
			return null;
		}

		return $this->data[$offset];
	}

	/**
	 * Set the given item
	 *
	 * @param string $offset Item name
	 * @param string $value Item value
	 *
	 * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`)
	 */
	#[ReturnTypeWillChange]
	public function offsetSet($offset, $value) {
		if ($offset === null) {
			throw new Exception('Object is a dictionary, not a list', 'invalidset');
		}

		if (is_string($offset)) {
			$offset = strtolower($offset);
		}

		$this->data[$offset] = $value;
	}

	/**
	 * Unset the given header
	 *
	 * @param string $offset The key for the item to unset.
	 */
	#[ReturnTypeWillChange]
	public function offsetUnset($offset) {
		if (is_string($offset)) {
			$offset = strtolower($offset);
		}

		unset($this->data[$offset]);
	}

	/**
	 * Get an iterator for the data
	 *
	 * @return \ArrayIterator
	 */
	#[ReturnTypeWillChange]
	public function getIterator() {
		return new ArrayIterator($this->data);
	}

	/**
	 * Get the headers as an array
	 *
	 * @return array Header data
	 */
	public function getAll() {
		return $this->data;
	}
}
FilteredIterator.php000064400000004155151535671430010544 0ustar00<?php
/**
 * Iterator for arrays requiring filtered values
 *
 * @package Requests\Utilities
 */

namespace WpOrg\Requests\Utility;

use ArrayIterator;
use ReturnTypeWillChange;
use WpOrg\Requests\Exception\InvalidArgument;
use WpOrg\Requests\Utility\InputValidator;

/**
 * Iterator for arrays requiring filtered values
 *
 * @package Requests\Utilities
 */
final class FilteredIterator extends ArrayIterator {
	/**
	 * Callback to run as a filter
	 *
	 * @var callable
	 */
	private $callback;

	/**
	 * Create a new iterator
	 *
	 * @param array    $data     The array or object to be iterated on.
	 * @param callable $callback Callback to be called on each value
	 *
	 * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not iterable.
	 */
	public function __construct($data, $callback) {
		if (InputValidator::is_iterable($data) === false) {
			throw InvalidArgument::create(1, '$data', 'iterable', gettype($data));
		}

		parent::__construct($data);

		if (is_callable($callback)) {
			$this->callback = $callback;
		}
	}

	/**
	 * Prevent unserialization of the object for security reasons.
	 *
	 * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound
	 *
	 * @param array $data Restored array of data originally serialized.
	 *
	 * @return void
	 */
	#[ReturnTypeWillChange]
	public function __unserialize($data) {}
	// phpcs:enable

	/**
	 * Perform reinitialization tasks.
	 *
	 * Prevents a callback from being injected during unserialization of an object.
	 *
	 * @return void
	 */
	public function __wakeup() {
		unset($this->callback);
	}

	/**
	 * Get the current item's value after filtering
	 *
	 * @return string
	 */
	#[ReturnTypeWillChange]
	public function current() {
		$value = parent::current();

		if (is_callable($this->callback)) {
			$value = call_user_func($this->callback, $value);
		}

		return $value;
	}

	/**
	 * Prevent creating a PHP value from a stored representation of the object for security reasons.
	 *
	 * @param string $data The serialized string.
	 *
	 * @return void
	 */
	#[ReturnTypeWillChange]
	public function unserialize($data) {}
}
InputValidator.php000064400000004720151535671430010237 0ustar00<?php
/**
 * Input validation utilities.
 *
 * @package Requests\Utilities
 */

namespace WpOrg\Requests\Utility;

use ArrayAccess;
use CurlHandle;
use Traversable;

/**
 * Input validation utilities.
 *
 * @package Requests\Utilities
 */
final class InputValidator {

	/**
	 * Verify that a received input parameter is of type string or is "stringable".
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function is_string_or_stringable($input) {
		return is_string($input) || self::is_stringable_object($input);
	}

	/**
	 * Verify whether a received input parameter is usable as an integer array key.
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function is_numeric_array_key($input) {
		if (is_int($input)) {
			return true;
		}

		if (!is_string($input)) {
			return false;
		}

		return (bool) preg_match('`^-?[0-9]+$`', $input);
	}

	/**
	 * Verify whether a received input parameter is "stringable".
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function is_stringable_object($input) {
		return is_object($input) && method_exists($input, '__toString');
	}

	/**
	 * Verify whether a received input parameter is _accessible as if it were an array_.
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function has_array_access($input) {
		return is_array($input) || $input instanceof ArrayAccess;
	}

	/**
	 * Verify whether a received input parameter is "iterable".
	 *
	 * @internal The PHP native `is_iterable()` function was only introduced in PHP 7.1
	 * and this library still supports PHP 5.6.
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function is_iterable($input) {
		return is_array($input) || $input instanceof Traversable;
	}

	/**
	 * Verify whether a received input parameter is a Curl handle.
	 *
	 * The PHP Curl extension worked with resources prior to PHP 8.0 and with
	 * an instance of the `CurlHandle` class since PHP 8.0.
	 * {@link https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.resource2object}
	 *
	 * @param mixed $input Input parameter to verify.
	 *
	 * @return bool
	 */
	public static function is_curl_handle($input) {
		if (is_resource($input)) {
			return get_resource_type($input) === 'curl';
		}

		if (is_object($input)) {
			return $input instanceof CurlHandle;
		}

		return false;
	}
}
AddressUtility.php000064400000002462151541645740010246 0ustar00<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Google\Service\ShoppingContent\AccountAddress;

defined( 'ABSPATH' ) || exit;

/**
 * Class AddressUtility
 *
 * @package Automattic\WooCommerce\GoogleListingsAndAds\Utility
 *
 * @since 1.4.0
 */
class AddressUtility implements Service {
	/**
	 * Checks whether two account addresses are the same and returns true if they are.
	 *
	 * @param AccountAddress $address_1
	 * @param AccountAddress $address_2
	 *
	 * @return bool True if the two addresses are the same, false otherwise.
	 */
	public function compare_addresses( AccountAddress $address_1, AccountAddress $address_2 ): bool {
		$cmp_street_address = $address_1->getStreetAddress() === $address_2->getStreetAddress();
		$cmp_locality       = $address_1->getLocality() === $address_2->getLocality();
		$cmp_region         = $address_1->getRegion() === $address_2->getRegion();
		$cmp_postal_code    = $address_1->getPostalCode() === $address_2->getPostalCode();
		$cmp_country        = $address_1->getCountry() === $address_2->getCountry();

		return $cmp_street_address && $cmp_locality && $cmp_region && $cmp_postal_code && $cmp_country;
	}
}
ArrayUtil.php000064400000000703151541645740007205 0ustar00<?php

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

/**
 * A class of utilities for dealing with arrays.
 *
 * @since 2.4.0
 */
class ArrayUtil {

	/**
	 * Remove empty values from array.
	 *
	 * @param array $strings A list of strings.
	 *
	 * @return array A list of strings without empty strings.
	 */
	public static function remove_empty_values( array $strings ): array {
		return array_values( array_filter( $strings ) );
	}
}
DateTimeUtility.php000064400000002027151541645740010352 0ustar00<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;

defined( 'ABSPATH' ) || exit;

/**
 * Class DateTimeUtility
 *
 * @package Automattic\WooCommerce\GoogleListingsAndAds\Utility
 *
 * @since 1.5.0
 */
class DateTimeUtility implements Service {

	/**
	 * Convert a timezone offset to the closest matching timezone string.
	 *
	 * @param string $timezone
	 *
	 * @return string
	 */
	public function maybe_convert_tz_string( string $timezone ): string {
		if ( preg_match( '/^([+-]\d{1,2}):?(\d{1,2})$/', $timezone, $matches ) ) {
			[ $timezone, $hours, $minutes ] = $matches;

			$sign    = (int) $hours >= 0 ? 1 : - 1;
			$seconds = $sign * ( absint( $hours ) * 60 * 60 + absint( $minutes ) * 60 );
			$tz_name = timezone_name_from_abbr( '', $seconds, 0 );

			$timezone = $tz_name !== false ? $tz_name : date_default_timezone_get();
		}

		if ( 'UTC' === $timezone ) {
			$timezone = 'Etc/GMT';
		}

		return $timezone;
	}
}
DimensionUtility.php000064400000002562151541645740010607 0ustar00<?php

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

/**
 * A class for dealing with Dimensions.
 *
 * @since 2.4.0
 */
class DimensionUtility {

	/**
	 * Width.
	 *
	 * @var int
	 */
	public int $x;
	/**
	 * Height.
	 *
	 * @var int
	 */
	public int $y;

	/**
	 * DimensionUtility constructor.
	 *
	 * @param int $x Width.
	 * @param int $y Height.
	 */
	public function __construct( int $x, int $y ) {
		$this->x = $x;
		$this->y = $y;
	}

	/**
	 * Checks if the dimension fulfils the minimum size.
	 *
	 * @param DimensionUtility $minimum_size The minimum size.
	 *
	 * @return bool true if the dimension is bigger or equal than the the minimum size otherwise false.
	 */
	public function is_minimum_size( DimensionUtility $minimum_size ): bool {
		return $this->x >= $minimum_size->x && $this->y >= $minimum_size->y;
	}

	/**
	 * Checks if the dimension is equal to the other one with a specific precision.
	 *
	 * @param DimensionUtility $target The dimension to be compared.
	 * @param int|float        $precision The precision to use when comparing the two numbers.
	 *
	 * @return bool true if the dimension is equal than the other one otherwise false.
	 */
	public function equals( DimensionUtility $target, $precision = 1 ): bool {
		return wp_fuzzy_number_match( $this->x, $target->x, $precision ) && wp_fuzzy_number_match( $this->y, $target->y, $precision );
	}
}
ISOUtility.php000064400000003551151541645740007313 0ustar00<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\League\ISO3166\Exception\ISO3166Exception;
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\League\ISO3166\ISO3166DataProvider;

defined( 'ABSPATH' ) || exit;

/**
 * Class ISOUtility
 *
 * @package Automattic\WooCommerce\GoogleListingsAndAds\Utility
 *
 * @since 1.5.0
 */
class ISOUtility implements Service {

	/**
	 * @var ISO3166DataProvider
	 */
	protected $iso3166_data_provider;

	/**
	 * ISOUtility constructor.
	 *
	 * @param ISO3166DataProvider $iso3166_data_provider
	 */
	public function __construct( ISO3166DataProvider $iso3166_data_provider ) {
		$this->iso3166_data_provider = $iso3166_data_provider;
	}

	/**
	 * Validate that the provided input is valid ISO 3166-1 alpha-2 country code.
	 *
	 * @param string $country_code
	 *
	 * @return bool
	 *
	 * @see https://wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements ISO 3166-1 alpha-2
	 *      officially assigned codes.
	 */
	public function is_iso3166_alpha2_country_code( string $country_code ): bool {
		try {
			$this->iso3166_data_provider->alpha2( $country_code );

			return true;
		} catch ( ISO3166Exception $exception ) {
			return false;
		}
	}

	/**
	 * Converts WordPress language code to IETF BCP 47 format.
	 *
	 * @param string $wp_locale
	 *
	 * @return string IETF BCP 47 language code or 'en-US' if the language code cannot be converted.
	 *
	 * @see https://tools.ietf.org/html/bcp47 IETF BCP 47 language codes.
	 */
	public function wp_locale_to_bcp47( string $wp_locale ): string {
		if ( empty( $wp_locale ) || ! preg_match( '/^[-_a-zA-Z0-9]{2,}$/', $wp_locale, $matches ) ) {
			return 'en-US';
		}

		return str_replace( '_', '-', $wp_locale );
	}
}
ImageUtility.php000064400000004617151541645740007707 0ustar00<?php

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

use Automattic\WooCommerce\GoogleListingsAndAds\Utility\DimensionUtility;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WP;

/**
 * A class of utilities for dealing with images.
 *
 * @since 2.4.0
 */
class ImageUtility implements Service {

	/**
	 * The WP Proxy.
	 *
	 * @var WP
	 */
	protected WP $wp;

	/**
	 * ImageUtility constructor.
	 *
	 * @param WP $wp WP Proxy.
	 */
	public function __construct( WP $wp ) {
		$this->wp = $wp;
	}

	/**
	 * Maybe add a new subsize image.
	 *
	 * @param int              $attachment_id Attachment ID.
	 * @param string           $subsize_key The subsize key that we are trying to generate.
	 * @param DimensionUtility $size The new size for the subsize key.
	 * @param bool             $crop Whether to crop the image.
	 *
	 * @return bool True if the subsize has been added to the attachment metadata otherwise false.
	 */
	public function maybe_add_subsize_image( int $attachment_id, string $subsize_key, DimensionUtility $size, bool $crop = true ): bool {
		add_image_size( $subsize_key, $size->x, $size->y, $crop );

		$metadata = $this->wp->wp_update_image_subsizes( $attachment_id );

		remove_image_size( $subsize_key );

		if ( is_wp_error( $metadata ) ) {
			return false;
		}

		return isset( $metadata['sizes'][ $subsize_key ] );
	}

	/**
	 * Try to recommend a size using the real size, the recommended and the minimum.
	 *
	 * @param DimensionUtility $size Image size.
	 * @param DimensionUtility $recommended Recommended image size.
	 * @param DimensionUtility $minimum Minimum image size.
	 *
	 * @return DimensionUtility|bool False if does not fulfil the minimum size otherwise returns the suggested size.
	 */
	public function recommend_size( DimensionUtility $size, DimensionUtility $recommended, DimensionUtility $minimum ) {
		if ( ! $size->is_minimum_size( $minimum ) ) {
			return false;
		}

		$image_ratio       = $size->x / $size->y;
		$recommended_ratio = $recommended->x / $recommended->y;

		if ( $recommended_ratio > $image_ratio ) {
			$x = $size->x > $recommended->x ? $recommended->x : $size->x;
			$y = (int) floor( $x / $recommended_ratio );
		} else {
			$y = $size->y > $recommended->y ? $recommended->y : $size->y;
			$x = (int) floor( $y * $recommended_ratio );
		}

		return new DimensionUtility( $x, $y );
	}
}
WPCLIMigrationGTIN.php000064400000014312151541645740010504 0ustar00<?php
declare( strict_types=1 );

namespace Automattic\WooCommerce\GoogleListingsAndAds\Utility;

use Automattic\WooCommerce\GoogleListingsAndAds\HelperTraits\GTINMigrationUtilities;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Conditional;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable;
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service;
use Automattic\WooCommerce\GoogleListingsAndAds\Product\Attributes\AttributeManager;
use Automattic\WooCommerce\GoogleListingsAndAds\Product\ProductRepository;
use Exception;
use WP_CLI;

defined( 'ABSPATH' ) || exit;

/**
 * Class WPCLIMigrationGTIN
 * Creates a set of utility commands in WP CLI for GTIN Migration
 *
 * @package Automattic\WooCommerce\GoogleListingsAndAds\Utility
 *
 * @since 2.9.0
 */
class WPCLIMigrationGTIN implements Service, Registerable, Conditional {
	use GTINMigrationUtilities;

	/** @var AttributeManager  */
	public AttributeManager $attribute_manager;

	/** @var ProductRepository  */
	public ProductRepository $product_repository;

	/**
	 * Constructor
	 *
	 * @param ProductRepository $product_repository
	 * @param AttributeManager  $attribute_manager
	 */
	public function __construct( ProductRepository $product_repository, AttributeManager $attribute_manager ) {
		$this->product_repository = $product_repository;
		$this->attribute_manager  = $attribute_manager;
	}

	/**
	 * Register service and initialize hooks.
	 */
	public function register(): void {
		WP_CLI::add_hook( 'after_wp_load', [ $this, 'register_commands' ] );
	}

	/**
	 * Register the commands
	 */
	public function register_commands(): void {
		WP_CLI::add_command( 'wc g4wc gtin-migration start', [ $this, 'gtin_migration_start' ] );
	}

	/**
	 * Starts the GTIN migration in batches
	 */
	public function gtin_migration_start(): void {
		$batch_size   = $this->get_batch_size();
		$num_products = $this->get_total_products_count();
		WP_CLI::log( sprintf( 'Starting GTIN migration for %s products in the store.', $num_products ) );
		$progress     = WP_CLI\Utils\make_progress_bar( 'GTIN Migration', $num_products / $batch_size );
		$processed    = 0;
		$batch_number = 1;
		$start_time   = microtime( true );

		// First batch
		$items      = $this->get_items( $batch_number );
		$processed += $this->process_items( $items );
		$progress->tick();

		// Next batches
		while ( ! empty( $items ) ) {
			++$batch_number;
			$items      = $this->get_items( $batch_number );
			$processed += $this->process_items( $items );
			$progress->tick();
		}

		$progress->finish();
		$total_time = microtime( true ) - $start_time;

		// Issue a warning if nothing is migrated.
		if ( ! $processed ) {
			WP_CLI::warning( __( 'No GTIN were migrated.', 'google-listings-and-ads' ) );
			return;
		}

		WP_CLI::success(
			sprintf(
			/* Translators: %1$d is the number of migrated GTINS and %2$d is the execution time in seconds. */
				_n(
					'%1$d GTIN was migrated in %2$d seconds.',
					'%1$d GTIN were migrated in %2$d seconds.',
					$processed,
					'google-listings-and-ads'
				),
				$processed,
				$total_time
			)
		);
	}

	/**
	 * Get total of products in the store to be migrated.
	 *
	 * @return int The total number of products.
	 */
	private function get_total_products_count(): int {
		$args = [
			'status' => 'publish',
			'return' => 'ids',
			'type'   => [ 'simple', 'variation' ],
		];

		return count( $this->product_repository->find_ids( $args ) );
	}


	/**
	 * Get the items for the current batch
	 *
	 * @param int $batch_number
	 * @return int[] Array of WooCommerce product IDs
	 */
	private function get_items( int $batch_number ): array {
		return $this->product_repository->find_all_product_ids( $this->get_batch_size(), $this->get_query_offset( $batch_number ) );
	}

	/**
	 * Get the query offset based on a given batch number and the specified batch size.
	 *
	 * @param int $batch_number
	 *
	 * @return int
	 */
	protected function get_query_offset( int $batch_number ): int {
		return $this->get_batch_size() * ( $batch_number - 1 );
	}

	/**
	 * Get the batch size. By default, 100.
	 *
	 * @return int The batch size.
	 */
	private function get_batch_size(): int {
		return apply_filters( 'woocommerce_gla_batched_cli_size', 100 );
	}

	/**
	 * Process batch items.
	 *
	 * @param int[] $items A single batch of WooCommerce product IDs from the get_batch() method.
	 * @return int The number of items processed.
	 */
	protected function process_items( array $items ): int {
		// update the product core GTIN using G4W GTIN
		$products  = $this->product_repository->find_by_ids( $items );
		$processed = 0;

		foreach ( $products as $product ) {
			// process variations
			if ( $product instanceof \WC_Product_Variable ) {
				$variations = $product->get_children();
				$processed += $this->process_items( $variations );
				continue;
			}

			// void if core GTIN is already set.
			if ( $product->get_global_unique_id() ) {
				$this->debug( $this->error_gtin_already_set( $product ) );
				continue;
			}

			$gtin = $this->get_gtin( $product );
			if ( ! $gtin ) {
				$this->debug( $this->error_gtin_not_found( $product ) );
				continue;
			}

			$gtin = $this->prepare_gtin( $gtin );
			if ( ! is_numeric( $gtin ) ) {
				$this->debug( $this->error_gtin_invalid( $product, $gtin ) );
				continue;
			}

			try {
				$product->set_global_unique_id( $gtin );
				$product->save();
				++$processed;
				$this->debug( $this->successful_migrated_gtin( $product, $gtin ) );
			} catch ( Exception $e ) {
				$this->error( $this->error_gtin_not_saved( $product, $gtin, $e ) );
			}
		}

		return $processed;
	}

	/**
	 * Check if this Service is needed.
	 *
	 * @see https://make.wordpress.org/cli/handbook/guides/commands-cookbook/#include-in-a-plugin-or-theme
	 * @return bool
	 */
	public static function is_needed(): bool {
		return defined( 'WP_CLI' ) && WP_CLI;
	}

	/**
	 * Add some info in the debug console.
	 * Add --debug to see these logs in WP CLI
	 *
	 * @param string $message
	 * @return void
	 */
	protected function debug( string $message ): void {
		WP_CLI::debug( $message );
	}

	/**
	 * Add some info in the error console.
	 *
	 * @param string $message
	 * @return void
	 */
	protected function error( string $message ): void {
		WP_CLI::error( $message, false );
	}
}