first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
{
"name": "wpdesk\/wc-currency-switchers-integrations",
"authors": [
{
"name": "Grzegorz",
"email": "grola@wpdesk.pl"
}
],
"license": "MIT",
"require": {
"php": ">=7.0",
"psr\/container": "^1.0",
"wpdesk\/wp-builder": "^2.0",
"psr\/log": "^1.1"
},
"require-dev": {
"phpunit\/phpunit": "^5",
"wp-coding-standards\/wpcs": "^0.14.1",
"squizlabs\/php_codesniffer": "^3.0.2",
"wimg\/php-compatibility": "^8",
"mockery\/mockery": "*",
"10up\/wp_mock": "*"
},
"autoload": {
"psr-4": {
"FSVendor\\WPDesk\\WooCommerce\\CurrencySwitchers\\": "src\/"
}
},
"autoload-dev": {},
"scripts": {
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* Abstract converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
/**
* Abstract class for converters.
*/
abstract class AbstractConverter implements \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\SwitcherConverter, \Psr\Log\LoggerAwareInterface
{
use LoggerAwareTrait;
/**
* @inheritDoc
*/
abstract function convert($value);
/**
* @inheritDoc
*/
public function convert_array($values)
{
foreach ($values as $key => $value) {
if ($value) {
$values[$key] = $this->convert($value);
}
}
return $values;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Filter converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers;
use Psr\Log\LoggerInterface;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
/**
* Can add filter to convert currency.
*/
class FilterConverter implements \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* @var AbstractConverter
*/
private $converter;
/**
* @var string
*/
private $shipping_method_id;
/**
* @param SwitcherConverter $converter
* @param string $shipping_method_id
*/
public function __construct(\FSVendor\WPDesk\WooCommerce\CurrencySwitchers\SwitcherConverter $converter, $shipping_method_id)
{
$this->converter = $converter;
$this->shipping_method_id = $shipping_method_id;
}
public function hooks()
{
\add_filter($this->shipping_method_id . '/currency-switchers/amount', [$this, 'convert'], 10, 2);
}
/**
* @param float $amount_in_shop_currency
* @param LoggerInterface $logger
*
* @return float
*/
public function convert($amount_in_shop_currency, $logger = null)
{
if ($logger instanceof \Psr\Log\LoggerInterface) {
$this->converter->setLogger($logger);
}
return $this->converter->convert($amount_in_shop_currency);
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* Filter converters.
*
* @package WPDesk\WooCommerce\CurrencySwitchers
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher;
/**
* Can create filter converters.
*/
class FilterConvertersFactory implements \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
const PRIORITY_AFTER_DEFAULT = 100;
/**
* @var string
*/
private $shipping_method_id;
/**
* @param string $shipping_method_id .
*/
public function __construct($shipping_method_id)
{
$this->shipping_method_id = $shipping_method_id;
}
/**
* Hooks.
*/
public function hooks()
{
\add_action('woocommerce_multicurrency_loaded', array($this, 'create_woocommerce_multicurrency_filter_converter'));
\add_action('woocommerce_init', [$this, 'create_currency_switcher_woocommerce_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
\add_action('woocommerce_init', [$this, 'create_wcml_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
\add_action('woocommerce_init', [$this, 'create_aelia_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
\add_action('woocommerce_init', [$this, 'create_fox_currency_switcher_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
\add_action('woocommerce_init', [$this, 'create_wmcs_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
\add_action('woocommerce_init', [$this, 'create_curcy_filter_converter'], self::PRIORITY_AFTER_DEFAULT);
}
public function create_woocommerce_multicurrency_filter_converter()
{
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency\Converter(), $this->shipping_method_id))->hooks();
}
public function create_currency_switcher_woocommerce_filter_converter()
{
$alg_get_current_currency_code = 'alg_get_current_currency_code';
// php scoper faker.
$alg_wc_cs_get_currency_exchange_rate = 'alg_wc_cs_get_currency_exchange_rate';
// php scoper faker.
if (\function_exists($alg_get_current_currency_code) && \function_exists($alg_wc_cs_get_currency_exchange_rate)) {
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CurrencySwitcherWoocommerce\Converter(), $this->shipping_method_id))->hooks();
}
}
public function create_wcml_filter_converter()
{
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WCML\Converter(), $this->shipping_method_id))->hooks();
}
public function create_aelia_filter_converter()
{
$class = 'Aelia' . '\\WC\\CurrencySwitcher\\WC_Aelia_CurrencySwitcher';
// php scoper faker
if (\class_exists($class)) {
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\Aelia\Converter(), $this->shipping_method_id))->hooks();
}
}
public function create_fox_currency_switcher_filter_converter()
{
if (isset($GLOBALS['WOOCS'])) {
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\FoxCurrencySwitcher\Converter(), $this->shipping_method_id))->hooks();
}
}
public function create_wmcs_filter_converter()
{
$wmcs_convert_price = 'wmcs_convert_price';
// php scoper faker.
if (\function_exists($wmcs_convert_price)) {
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WMCS\Converter(), $this->shipping_method_id))->hooks();
}
}
public function create_curcy_filter_converter()
{
$wmc_get_price = 'wmc_get_price';
// php scoper faker.
if (\function_exists($wmc_get_price)) {
(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\FilterConverter(new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CURCY\Converter(), $this->shipping_method_id))->hooks();
}
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Shipping integrations.
*
* @package WPDesk\WooCommerce\CurrencySwitchers
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency\ShippingMethodIntegration;
/**
* Can create integrations for shipping methods.
* Creates integrations for plugins which do not works by default, ie. WooCommerce MultiCurrency.
* @see https://woocommerce.com/products/multi-currency/
*/
class ShippingIntegrations implements \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* @var string
*/
private $shipping_method_id;
/**
* @param string $shipping_method_id .
*/
public function __construct($shipping_method_id)
{
$this->shipping_method_id = $shipping_method_id;
}
/**
* Hooks.
*/
public function hooks()
{
\add_action('woocommerce_loaded', array($this, 'add_integrations_for_shipping_method'));
}
/**
* Add integration to WooCommerce MultiCurrency for shipping method.
*/
public function add_integrations_for_shipping_method()
{
$woocommerce_multicurrency_integration = new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency\ShippingMethodIntegration($this->shipping_method_id);
$woocommerce_multicurrency_integration->hooks();
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\Aelia
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\Aelia;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using Aelia Currency Switcher plugin.
* @see https://aelia.co/shop/currency-switcher-woocommerce/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
$class = 'Aelia' . '\\WC\\CurrencySwitcher\\WC_Aelia_CurrencySwitcher';
// php scoper faker
$aelia = $class::instance();
$aelia_settings = $class::settings();
$from_currency = $aelia_settings->base_currency();
$to_currency = $aelia->get_selected_currency();
return $aelia->convert($value, $from_currency, $to_currency);
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\CURCY
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CURCY;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using CURCY Multi Currency for WooCommerce plugin.
* @see https://wordpress.org/plugins/woo-multi-currency/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
return wmc_get_price($value);
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\CurrencySwitcherWoocommerce
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CurrencySwitcherWoocommerce;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using Currency Switcher for WooCommerce plugin.
* @see https://wordpress.org/plugins/currency-switcher-woocommerce/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
$currency_exchange_rate = alg_wc_cs_get_currency_exchange_rate(alg_get_current_currency_code());
return $value * $currency_exchange_rate;
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\FoxCurrencySwitcher
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\FoxCurrencySwitcher;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
use function FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CurrencySwitcherWoocommerce\alg_get_current_currency_code;
use function FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\CurrencySwitcherWoocommerce\alg_wc_cs_get_currency_exchange_rate;
/**
* Can convert currency using FOX Currency Switcher Professional for WooCommerce plugin.
* @see https://wordpress.org/plugins/woocommerce-currency-switcher/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
return $GLOBALS['WOOCS'] ? $GLOBALS['WOOCS']->woocs_exchange_value($value) : $value;
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\WCML
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WCML;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using Currency Switcher for WooCommerce plugin.
* @see https://wordpress.org/plugins/woocommerce-multilingual/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
return \apply_filters('wcml_raw_price_amount', $value);
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\WMCS
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WMCS;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using WMCS plugin.
* Unknown plugin URL. This is legacy from Flexible Shipping
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
return wmcs_convert_price($value);
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Currency converter.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency;
use FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter;
/**
* Can convert currency using WooCommerce MultiCurrency plugin.
* @see https://woocommerce.com/products/multi-currency/
*/
class Converter extends \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\AbstractConverter
{
/**
* @inheritDoc
*/
public function convert($value)
{
try {
$rate_storage = new \WOOMC\Rate\Storage();
$price_rounder = new \WOOMC\Price\Rounder();
$currency_detector = new \WOOMC\Currency\Detector();
$price_calculator = new \WOOMC\Price\Calculator($rate_storage, $price_rounder);
$price_controller = new \WOOMC\Price\Controller($price_calculator, $currency_detector);
return $price_controller->convert($value);
} catch (\Throwable $e) {
if ($this->logger) {
$this->logger->debug($e->getMessage());
}
}
return $value;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Shipping method controler.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency;
use FSVendor\WP_Mock\Hook;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
/**
* Converts shipping costs and taxes from shop currency to current currency.
*/
class ShippingMethodController implements \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* @var string
*/
private $shipping_method_id;
/**
*
* @var Converter
*/
protected $converter;
/**
* @param string $shipping_method_id .
* @param Converter $converter .
*/
public function __construct($shipping_method_id, $converter)
{
$this->shipping_method_id = $shipping_method_id;
$this->converter = $converter;
}
/**
* Hooks.
*/
public function hooks()
{
\add_filter('woocommerce_shipping_rate_cost', array($this, 'convert_shipping_rate_costs_for_shipping_method'), 10, 2);
\add_filter('woocommerce_shipping_rate_taxes', array($this, 'convert_shipping_rate_taxes_for_shipping_method'), 10, 2);
}
/**
* Filter the rate cost.
*
* @param float|int|string $cost The shipping rate cost.
* @param \WC_Shipping_Rate $shipping_rate_object The shipping rate object.
*
* @return float|int|string
* @internal filter.
*/
public function convert_shipping_rate_costs_for_shipping_method($cost, $shipping_rate_object)
{
if ($this->is_shipping_method($shipping_rate_object)) {
$cost = $this->converter->convert($cost);
}
return $cost;
}
/**
* Filter the taxes.
*
* @param float[]|int[]|string[] $taxes The shipping rate taxes array.
* @param \WC_Shipping_Rate $shipping_rate_object The shipping rate object.
*
* @return float[]|int[]|string[]
* @internal filter.
*/
public function convert_shipping_rate_taxes_for_shipping_method($taxes, $shipping_rate_object)
{
if ($this->is_shipping_method($shipping_rate_object)) {
$taxes = $this->converter->convert_array($taxes);
}
return $taxes;
}
/**
* Check if the shipping rate object's method ID is relevant to this class.
*
* @param \WC_Shipping_Rate $shipping_rate_object The shipping rate object.
*
* @return bool
*/
private function is_shipping_method($shipping_rate_object)
{
return $shipping_rate_object instanceof \WC_Shipping_Rate && $this->shipping_method_id === $shipping_rate_object->get_method_id();
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Shipping method integration.
*
* @package WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency;
use FSVendor\WPDesk\PluginBuilder\Plugin\Hookable;
/**
* Integrates shipping method (by method_id, ie.: flexible_shipping ) with WooCommerce Multicurrency plugin.
* @see https://woocommerce.com/products/multi-currency/
*/
class ShippingMethodIntegration implements \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* @var string
*/
private $shipping_method_id;
/**
* @var \WOOMC\Integration\Shipping\AbstractController
*/
private $woocommerce_multicurrency_controller;
/**
* @param string $shipping_method_id .
*/
public function __construct($shipping_method_id)
{
$this->shipping_method_id = $shipping_method_id;
}
/**
* Hooks.
*/
public function hooks()
{
\add_action('woocommerce_multicurrency_loaded', array($this, 'add_integration_for_shipping_method'));
}
/**
* Add integration to WooCommerce MultiCurrency for shipping method.
*/
public function add_integration_for_shipping_method()
{
$this->woocommerce_multicurrency_controller = new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency\ShippingMethodController($this->shipping_method_id, new \FSVendor\WPDesk\WooCommerce\CurrencySwitchers\Switcher\WooCommerceMultiCurrency\Converter());
$this->woocommerce_multicurrency_controller->hooks();
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* Interface Converter
* @package WPDesk\WooCommerce\CurrencySwitchers
*/
namespace FSVendor\WPDesk\WooCommerce\CurrencySwitchers;
/**
* Interface for currency switchers converters.
*/
interface SwitcherConverter
{
/**
* Convert value from shop currency to current currency.
*
* @param float $value Value in shop currency.
*
* @return float
*/
public function convert($value);
/**
* Convert an array of prices.
*
* @return array
* @example convert_array( ['price' => '10', 'sale_price' => 5] ) --> ['price' => '12.4', 'sale_price' => 6.2]
*/
public function convert_array($values);
}

View File

@@ -0,0 +1,35 @@
{
"name": "wpdesk\/wp-abtesting",
"authors": [
{
"name": "Krzysiek",
"email": "krzysiek@wpdesk.pl"
}
],
"require": {
"php": ">=5.6",
"wpdesk\/wp-persistence": "^2.0"
},
"require-dev": {
"phpunit\/phpunit": "^5",
"wp-coding-standards\/wpcs": "^0.14.1",
"squizlabs\/php_codesniffer": "^3.0.2",
"wimg\/php-compatibility": "^8"
},
"autoload": {
"psr-4": {
"FSVendor\\WPDesk\\ABTesting\\": "src\/"
}
},
"autoload-dev": {
"psr-4": {
"FSVendor\\WPDesk\\ABTesting\\Tests\\Unit\\": "tests\/unit\/"
}
},
"scripts": {
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace FSVendor\WPDesk\ABTesting;
/**
* Test should know what variant should be used and that is all.
*
* @package WPDesk\ABTesting
*/
interface ABTest
{
/**
* Return info about what variant of AB test should be used.
*
* @return ABVariant
*/
public function get_variant();
}

View File

@@ -0,0 +1,103 @@
<?php
namespace FSVendor\WPDesk\ABTesting\ABTest;
use FSVendor\WPDesk\ABTesting\ABTest;
use FSVendor\WPDesk\Persistence\ElementNotExistsException;
use FSVendor\WPDesk\Persistence\PersistentContainer;
/**
* Base class for AB tests with equal groups generated by random number generator
*
* @package WPDesk\ABTesting\ABTest
*/
abstract class EqualGroupsRandomABTest implements \FSVendor\WPDesk\ABTesting\ABTest
{
const CONTAINER_VALUE_PREFIX = 'ab_test';
/**
* Used to save info about generated variant
*
* @var PersistentContainer
*/
private $container;
/**
* How many groups/variants are in the whole test
*
* @var int
*/
private $variant_count;
/**
* Some unique test name for persitence pusposes and for higher readability
*
* @var string
*/
private $test_name;
/**
* Derived classes can use this value to know what variant id is generated
*
* @var int
*/
protected $current_variant_id;
/**
* @param int $variant_count Number of equal size groups to generate.
* @param string $test_name Specific test name. Should be unique. Used to persist.
* @param PersistentContainer $container Container to persist data.
*/
public function __construct($variant_count, $test_name, \FSVendor\WPDesk\Persistence\PersistentContainer $container)
{
\assert(\is_int($variant_count) && $variant_count > 0, '$variant_count makes no sense');
$this->variant_count = $variant_count;
$this->test_name = $test_name;
$this->container = $container;
$this->initialize_variant_id();
}
/**
* Clears info about variant and draws again
*/
public function reset()
{
$this->container->set($this->get_container_key(), null);
$this->initialize_variant_id();
}
/**
* @return void
*/
private function initialize_variant_id()
{
$variant_id = $this->get_variant_id_from_container();
if ($variant_id === null) {
$variant_id = $this->generate_variant_id();
$this->container->set($this->get_container_key(), $variant_id);
}
$this->current_variant_id = $variant_id;
}
/**
* Returns variant id if exists.
*
* @return int|null Returns null if not exists.
*/
private function get_variant_id_from_container()
{
try {
$variant_id = $this->container->get($this->get_container_key());
return (int) $variant_id;
} catch (\FSVendor\WPDesk\Persistence\ElementNotExistsException $e) {
return null;
}
}
/**
* Key for where variant id should be saved in the persistence container
*
* @return string
*/
protected function get_container_key()
{
return \implode('_', [self::CONTAINER_VALUE_PREFIX, $this->test_name, 'variant_id']);
}
/**
* @return int
*/
private function generate_variant_id()
{
return \mt_rand(1, $this->variant_count);
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace FSVendor\WPDesk\ABTesting;
/**
* Specific variant should know what functionalities should be on/off.
*
* @package WPDesk\ABTesting
*/
interface ABVariant
{
/**
* Checks if a variant does have a given functionality working.
*
* @param string $functionality
*
* @return bool
*/
public function is_on($functionality);
/**
* Returns the variant id (can be numeric). For example for standard AB testing it would be A or B.
*
* @return string
*/
public function get_variant_id();
}

View File

@@ -0,0 +1,27 @@
<?php
namespace FSVendor\WPDesk\ABTesting\ABVariant;
use FSVendor\WPDesk\ABTesting\ABVariant;
/**
* Base class for variants. Nothing special.
*
* @package WPDesk\ABTesting\ABVariant
*/
abstract class BasicABVariant implements \FSVendor\WPDesk\ABTesting\ABVariant
{
/** @var string */
private $variant_id;
/**
* @param string $variant_id
*/
public function __construct($variant_id)
{
$this->variant_id = (string) $variant_id;
}
public abstract function is_on($functionality);
public function get_variant_id()
{
return $this->variant_id;
}
}

View File

@@ -0,0 +1,51 @@
{
"name": "wpdesk\/wp-basic-requirements",
"authors": [
{
"name": "Krzysiek",
"email": "krzysiek@wpdesk.pl"
}
],
"require": {
"php": ">=5.3"
},
"require-dev": {
"php": ">=5.5",
"phpunit\/phpunit": "^8 | ^9",
"mockery\/mockery": "*",
"10up\/wp_mock": "*",
"wimg\/php-compatibility": "^8",
"wpdesk\/wp-code-sniffer": "^1.2"
},
"autoload": {},
"autoload-dev": {
"classmap": [
"src",
"tests"
]
},
"extra": {
"text-domain": "wp-basic-requirements",
"translations-folder": "lang",
"po-files": {
"pl_PL": "pl_PL.po",
"en_AU": "en_AU.po",
"en_CA": "en_CA.po",
"en_GB": "en_GB.po",
"de_DE": "de_DE.po"
}
},
"scripts": {
"phpcs": "phpcs",
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage",
"docs": "apigen generate"
},
"config": {
"allow-plugins": {
"dealerdirect\/phpcodesniffer-composer-installer": true
}
}
}

View File

@@ -0,0 +1,602 @@
<?php
namespace FSVendor;
if (!\interface_exists('FSVendor\\WPDesk_Requirement_Checker')) {
require_once __DIR__ . '/Requirement_Checker.php';
}
if (!\class_exists('FSVendor\\WPDesk_Basic_Requirement_Checker')) {
/**
* Checks requirements for plugin
* have to be compatible with PHP 5.3.x
*/
class WPDesk_Basic_Requirement_Checker implements \FSVendor\WPDesk_Requirement_Checker
{
const EXTENSION_NAME_OPENSSL = 'openssl';
const HOOK_ADMIN_NOTICES_ACTION = 'admin_notices';
const HOOK_PLUGIN_DEACTIVATED_ACTION = 'deactivated_plugin';
const HOOK_PLUGIN_ACTIVATED_ACTION = 'activated_plugin';
const PLUGIN_INFO_KEY_NICE_NAME = 'nice_name';
const PLUGIN_INFO_KEY_NAME = 'name';
const PLUGIN_INFO_VERSION = 'version';
const PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION = '0.0';
const PLUGIN_INFO_APPEND_PLUGIN_DATA = 'required_version';
const PLUGIN_INFO_TRANSIENT_NAME = 'wpdesk_requirements_plugins_data';
const CACHE_TIME = 16;
const EXPIRATION_TIME = 'expiration_time';
const PLUGINS = 'plugins';
/** @var string */
protected $plugin_name;
/** @var string */
private $plugin_file;
/** @var string */
private $min_php_version;
/** @var string */
private $min_wp_version;
/** @var string|null */
private $min_wc_version = null;
/** @var int|null */
private $min_openssl_version = null;
/** @var array */
protected $plugin_require;
/** @var bool */
protected $should_check_plugin_versions = \false;
/** @var array */
private $module_require;
/** @var array */
private $setting_require;
/** @var array */
protected $notices;
/** @var @string */
private $text_domain;
/**
* @var mixed|true
*/
private $use_transients;
/**
* @param string $plugin_file
* @param string $plugin_name
* @param string $text_domain
* @param string $php_version
* @param string $wp_version
* @param bool $use_transients
*/
public function __construct($plugin_file, $plugin_name, $text_domain, $php_version, $wp_version, $use_transients = \true)
{
$this->plugin_file = $plugin_file;
$this->plugin_name = $plugin_name;
$this->text_domain = $text_domain;
$this->use_transients = $use_transients;
$this->set_min_php_require($php_version);
$this->set_min_wp_require($wp_version);
$this->plugin_require = array();
$this->module_require = array();
$this->setting_require = array();
$this->notices = array();
}
/**
* @param string $version
*
* @return $this
*/
public function set_min_php_require($version)
{
$this->min_php_version = $version;
return $this;
}
/**
* @param string $version
*
* @return $this
*/
public function set_min_wp_require($version)
{
$this->min_wp_version = $version;
return $this;
}
/**
* @param string $version
*
* @return $this
*/
public function set_min_wc_require($version)
{
$this->min_wc_version = $version;
return $this;
}
/**
* @param $version
*
* @return $this
*/
public function set_min_openssl_require($version)
{
$this->min_openssl_version = $version;
return $this;
}
/**
* @param string $plugin_name Name in wp format dir/file.php
* @param string $nice_plugin_name Nice plugin name for better looks in notice
* @param string $plugin_require_version required plugin minimum version
*
* @return $this
*/
public function add_plugin_require($plugin_name, $nice_plugin_name = null, $plugin_require_version = null)
{
if ($plugin_require_version) {
$this->should_check_plugin_versions = \true;
}
$this->plugin_require[$plugin_name] = array(self::PLUGIN_INFO_KEY_NAME => $plugin_name, self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name, self::PLUGIN_INFO_VERSION => $plugin_require_version === null ? self::PLUGIN_INFO_FAKE_REQUIRED_MINIMUM_VERSION : $plugin_require_version);
return $this;
}
/**
* Add plugin to require list. Plugin is from repository so we can ask for installation.
*
* @param string $plugin_name Name in wp format dir/file.php
* @param string $version Required version of the plugin.
* @param string $nice_plugin_name Nice plugin name for better looks in notice
*
* @return $this
*/
public function add_plugin_repository_require($plugin_name, $version, $nice_plugin_name = null)
{
$this->plugin_require[$plugin_name] = array(self::PLUGIN_INFO_KEY_NAME => $plugin_name, self::PLUGIN_INFO_VERSION => $version, 'repository_url' => 'http://downloads.wordpress.org/plugin/' . \dirname($plugin_name) . '.latest-stable.zip', self::PLUGIN_INFO_KEY_NICE_NAME => $nice_plugin_name === null ? $plugin_name : $nice_plugin_name);
return $this;
}
/**
* @param string $module_name
* @param string $nice_name Nice module name for better looks in notice
*
* @return $this
*/
public function add_php_module_require($module_name, $nice_name = null)
{
if ($nice_name === null) {
$this->module_require[$module_name] = $module_name;
} else {
$this->module_require[$module_name] = $nice_name;
}
return $this;
}
/**
* @param string $setting
* @param mixed $value
*
* @return $this
*/
public function add_php_setting_require($setting, $value)
{
$this->setting_require[$setting] = $value;
return $this;
}
/**
* Returns true if are requirements are met.
*
* @return bool
*/
public function are_requirements_met()
{
$this->notices = $this->prepare_requirement_notices();
return \count($this->notices) === 0;
}
/**
* @return array
*/
private function prepare_requirement_notices()
{
$notices = array();
if (!self::is_php_at_least($this->min_php_version)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run on PHP versions older than %s. Please contact your host and ask them to upgrade.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_php_version));
}
if (!self::is_wp_at_least($this->min_wp_version)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run on WordPress versions older than %s. Please update WordPress.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_wp_version));
}
if ($this->min_wc_version !== null && $this->can_check_plugin_version() && !self::is_wc_at_least($this->min_wc_version)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run on WooCommerce versions older than %s. Please update WooCommerce.', $this->get_text_domain()), \esc_html($this->plugin_name), $this->min_wc_version));
}
if ($this->min_openssl_version !== null && !self::is_open_ssl_at_least($this->min_openssl_version)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run without OpenSSL module version at least %s. Please update OpenSSL module.', $this->get_text_domain()), \esc_html($this->plugin_name), '0x' . \dechex($this->min_openssl_version)));
}
$notices = $this->append_plugin_require_notices($notices);
$notices = $this->append_module_require_notices($notices);
$notices = $this->append_settings_require_notices($notices);
if ($this->should_check_plugin_versions) {
$notices = $this->check_minimum_require_plugins_version_and_append_notices($notices);
}
return $notices;
}
/**
* @param $min_version
*
* @return mixed
*/
public static function is_php_at_least($min_version)
{
return \version_compare(\PHP_VERSION, $min_version, '>=');
}
/**
* Prepares message in html format
*
* @param string $message
*
* @return string
*/
protected function prepare_notice_message($message)
{
return '<div class="error"><p>' . $message . '</p></div>';
}
public function get_text_domain()
{
return $this->text_domain;
}
/**
* @param string $min_version
*
* @return bool
*/
public static function is_wp_at_least($min_version)
{
return \version_compare(\get_bloginfo('version'), $min_version, '>=');
}
/**
* Are plugins loaded so we can check the version
*
* @return bool
*/
private function can_check_plugin_version()
{
return \did_action('plugins_loaded') > 0;
}
/**
* Checks if plugin is active and have designated version. Needs to be enabled in deferred way.
*
* @param string $min_version
*
* @return bool
*/
public static function is_wc_at_least($min_version)
{
return \defined('WC_VERSION') && \version_compare(\WC_VERSION, $min_version, '>=');
}
/**
* Checks if ssl version is valid
*
* @param int $required_version Version in hex. Version 9.6 is 0x000906000
*
* @return bool
* @see https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_VERSION_NUMBER.html
*
*/
public static function is_open_ssl_at_least($required_version)
{
return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER > (int) $required_version;
}
/**
* @param $notices array
*
* @return array
*/
private function check_minimum_require_plugins_version_and_append_notices($notices)
{
$required_plugins = $this->retrieve_required_plugins_data();
if (\count($required_plugins) > 0) {
foreach ($required_plugins as $plugin) {
if (\version_compare($plugin['Version'], $plugin[self::PLUGIN_INFO_APPEND_PLUGIN_DATA], '<=')) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%1$s&#8221; plugin requires at least %2$s version of %3$s to work correctly. Please update it to its latest release.', $this->get_text_domain()), \esc_html($this->plugin_name), $plugin[self::PLUGIN_INFO_APPEND_PLUGIN_DATA], $plugin['Name']));
}
}
}
return $notices;
}
/**
* Check the plugins directory and retrieve all plugin files with plugin data.
*
* @param bool $use_transients
*
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', ...], ]
*/
private static function retrieve_plugins_data_in_transient($use_transients = \true)
{
$current_time = \time();
$plugins = self::get_plugins_data_from_cache($use_transients, $current_time);
if ($plugins === \false) {
static $never_executed = \true;
if ($never_executed) {
$never_executed = \false;
/** Required when WC starts later and these data should be in cache */
\add_filter('extra_plugin_headers', function ($headers = array()) {
$headers[] = 'WC tested up to';
$headers[] = 'WC requires at least';
$headers[] = 'Woo';
return \array_unique($headers);
});
}
if (!\function_exists('get_plugins')) {
require_once \ABSPATH . '/wp-admin/includes/plugin.php';
}
$plugins = \function_exists('get_plugins') ? \get_plugins() : array();
self::update_plugins_data_in_cache($plugins, $use_transients, $current_time);
}
return $plugins;
}
/**
* @param bool $use_transients
* @param int $current_time
*
* @return array|false
*/
private static function get_plugins_data_from_cache($use_transients, $current_time)
{
if ($use_transients) {
return \get_transient(self::PLUGIN_INFO_TRANSIENT_NAME);
} else {
$plugins_option_value = \get_option(self::PLUGIN_INFO_TRANSIENT_NAME);
if (\is_array($plugins_option_value) && isset($plugins_option_value[self::EXPIRATION_TIME], $plugins_option_value[self::PLUGINS]) && (int) $plugins_option_value[self::EXPIRATION_TIME] > $current_time) {
return $plugins_option_value[self::PLUGINS];
}
}
return \false;
}
/**
* @param array $plugins
* @param bool $use_transients
* @param int $current_time
*/
private static function update_plugins_data_in_cache($plugins, $use_transients, $current_time)
{
if ($use_transients) {
\set_transient(self::PLUGIN_INFO_TRANSIENT_NAME, $plugins, self::CACHE_TIME);
} else {
\update_option(self::PLUGIN_INFO_TRANSIENT_NAME, array(self::EXPIRATION_TIME => $current_time + self::CACHE_TIME, self::PLUGINS => $plugins));
}
}
/**
* Check the plugins directory and retrieve all required plugin files with plugin data.
*
* @return array In format [ 'plugindir/pluginfile.php' => ['Name' => 'Plugin Name', 'Version' => '1.0.1', 'required_version' => '1.0.2']... ]
*/
private function retrieve_required_plugins_data()
{
$require_plugins = array();
$plugins = self::retrieve_plugins_data_in_transient($this->use_transients);
if (\is_array($plugins)) {
if (\count($plugins) > 0) {
if (!empty($this->plugin_require)) {
foreach ($this->plugin_require as $plugin) {
$plugin_file_name = $plugin[self::PLUGIN_INFO_KEY_NAME];
$plugin_version = $plugin[self::PLUGIN_INFO_VERSION];
if (self::is_wp_plugin_active($plugin_file_name)) {
$require_plugins[$plugin_file_name] = $plugins[$plugin_file_name];
$require_plugins[$plugin_file_name][self::PLUGIN_INFO_APPEND_PLUGIN_DATA] = $plugin_version;
}
}
}
}
}
return $require_plugins;
}
/**
* @param array $notices
*
* @return array
*/
private function append_plugin_require_notices($notices)
{
if (\count($this->plugin_require) > 0) {
foreach ($this->plugin_require as $plugin_name => $plugin_info) {
$notice = null;
if (isset($plugin_info['repository_url'])) {
$notice = $this->prepare_plugin_repository_require_notice($plugin_info);
} elseif (!self::is_wp_plugin_active($plugin_name)) {
$notice = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run without %s active. Please install and activate %s plugin.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME])), \esc_html(\basename($plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME]))));
}
if ($notice !== null) {
$notices[] = $notice;
}
}
}
return $notices;
}
/**
* Prepares WP install url and injects info about plugin to the WP update engine.
*
* @param array $plugin_info
*
* @return string
*/
private function prepare_plugin_repository_install_url($plugin_info)
{
$slug = \basename($plugin_info[self::PLUGIN_INFO_KEY_NAME]);
$install_url = \self_admin_url('update.php?action=install-plugin&plugin=' . $slug);
if (\function_exists('wp_nonce_url') && \function_exists('wp_create_nonce')) {
$install_url = \wp_nonce_url($install_url, 'install-plugin_' . $slug);
}
\add_filter('plugins_api', function ($api, $action, $args) use($plugin_info, $slug) {
if ('plugin_information' !== $action || \false !== $api || !isset($args->slug) || $slug !== $args->slug) {
return $api;
}
$api = new \stdClass();
$api->name = $plugin_info['nice_name'];
// self in closures requires 5.4
$api->version = '';
$api->download_link = \esc_url($plugin_info['repository_url']);
// self in closures requires 5.4
return $api;
}, 10, 3);
return $install_url;
}
/**
* @param array $plugin_info Internal required plugin info data.
*
* @return string|null Return null if no notice is needed.
*/
private function prepare_plugin_repository_require_notice($plugin_info)
{
$name = $plugin_info[self::PLUGIN_INFO_KEY_NAME];
$nice_name = $plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME];
if (!self::is_wp_plugin_active($name)) {
if (!self::is_wp_plugin_installed($name, $this->use_transients)) {
$install_url = $this->prepare_plugin_repository_install_url($plugin_info);
return $this->prepare_notice_message(\sprintf(\wp_kses(\__('The &#8220;%s&#8221; plugin requires free %s plugin. <a href="%s">Install %s</a>', $this->get_text_domain()), array('a' => array('href' => array()))), $this->plugin_name, $nice_name, \esc_url($install_url), $nice_name));
}
$activate_url = 'plugins.php?action=activate&plugin=' . \urlencode($plugin_info[self::PLUGIN_INFO_KEY_NAME]) . '&plugin_status=all&paged=1&s';
if (\function_exists('wp_create_nonce')) {
$activate_url .= '&_wpnonce=' . \urlencode(\wp_create_nonce('activate-plugin_' . $name));
}
return $this->prepare_notice_message(\sprintf(\wp_kses(\__('The &#8220;%s&#8221; plugin requires activating %s plugin. <a href="%s">Activate %s</a>', $this->get_text_domain()), array('a' => array('href' => array()))), $this->plugin_name, $nice_name, \esc_url(\admin_url($activate_url)), $nice_name));
}
return null;
}
/**
* Checks if plugin is active. Needs to be used in deferred way.
*
* @param string $plugin_file
*
* @return bool
*/
public static function is_wp_plugin_active($plugin_file)
{
$active_plugins = (array) \get_option('active_plugins', array());
if (\is_multisite()) {
$active_plugins = \array_merge($active_plugins, \get_site_option('active_sitewide_plugins', array()));
}
return \in_array($plugin_file, $active_plugins) || \array_key_exists($plugin_file, $active_plugins);
}
/**
* Checks if plugin is installed. Needs to be enabled in deferred way.
*
* @param string $plugin_file
* @param bool $use_transients
*
* @return bool
*/
public static function is_wp_plugin_installed($plugin_file, $use_transients = \false)
{
$plugins_data = self::retrieve_plugins_data_in_transient($use_transients);
return \array_key_exists($plugin_file, (array) $plugins_data);
}
/**
* @param array $notices
*
* @return array
*/
private function append_module_require_notices($notices)
{
if (\count($this->module_require) > 0) {
foreach ($this->module_require as $module_name => $nice_module_name) {
if (!self::is_module_active($module_name)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run without %s PHP module installed. Please contact your host and ask them to install %s.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($nice_module_name)), \esc_html(\basename($nice_module_name))));
}
}
}
return $notices;
}
/**
* @param string $name
*
* @return bool
*/
public static function is_module_active($name)
{
return \extension_loaded($name);
}
/**
* @param array $notices
*
* @return array
*/
private function append_settings_require_notices($notices)
{
if (\count($this->setting_require) > 0) {
foreach ($this->setting_require as $setting => $value) {
if (!self::is_setting_set($setting, $value)) {
$notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin cannot run without %s PHP setting set to %s. Please contact your host and ask them to set %s.', $this->get_text_domain()), \esc_html($this->plugin_name), \esc_html(\basename($setting)), \esc_html(\basename($value)), \esc_html(\basename($setting))));
}
}
}
return $notices;
}
/**
* @param string $name
* @param mixed $value
*
* @return bool
*/
public static function is_setting_set($name, $value)
{
return \ini_get($name) === (string) $value;
}
/**
* @return void
*
* @deprecated use render_notices or disable_plugin
*/
public function disable_plugin_render_notice()
{
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_render_notices_action'));
}
/**
* Renders requirement notices in admin panel
*
* @return void
*/
public function render_notices()
{
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_render_notices_action'));
}
/**
* Renders requirement notices in admin panel
*
* @return void
*/
public function disable_plugin()
{
\add_action(self::HOOK_ADMIN_NOTICES_ACTION, array($this, 'handle_deactivate_action'));
}
/**
* @return void
* @internal Do not use as public. Public only for wp action.
*
*/
public function handle_deactivate_action()
{
if (isset($this->plugin_file)) {
\deactivate_plugins(\plugin_basename($this->plugin_file));
$this->clear_plugin_info_data();
}
}
/**
* Triggers the transient delete after plugin deactivated
*
* @return void
*/
public function transient_delete_on_plugin_version_changed()
{
\add_action(self::HOOK_PLUGIN_DEACTIVATED_ACTION, array($this, 'clear_plugin_info_data'));
\add_action(self::HOOK_PLUGIN_ACTIVATED_ACTION, array($this, 'clear_plugin_info_data'));
}
/**
* Handles the transient delete
*
* @return void
*/
public function clear_plugin_info_data()
{
\delete_transient(self::PLUGIN_INFO_TRANSIENT_NAME);
\delete_option(self::PLUGIN_INFO_TRANSIENT_NAME);
}
/**
* Should be called as WordPress action
*
* @return void
* @internal Do not use as public. Public only for wp action.
*
*/
public function handle_render_notices_action()
{
foreach ($this->notices as $notice) {
echo $notice;
}
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace FSVendor;
if (!\class_exists('FSVendor\\Basic_Requirement_Checker')) {
require_once __DIR__ . '/Basic_Requirement_Checker.php';
}
if (!\class_exists('FSVendor\\WPDesk_Basic_Requirement_Checker_With_Update_Disable')) {
require_once __DIR__ . '/Basic_Requirement_Checker_With_Update_Disable.php';
}
/**
* Falicitates createion of requirement checker
*/
class WPDesk_Basic_Requirement_Checker_Factory
{
const LIBRARY_TEXT_DOMAIN = 'flexible-shipping';
/**
* Creates a simplest possible version of requirement checker.
*
* @param string $plugin_file
* @param string $plugin_name
* @param string|null $text_domain Text domain to use. If null try to use library text domain.
*
* @return WPDesk_Requirement_Checker
*/
public function create_requirement_checker($plugin_file, $plugin_name, $text_domain = null)
{
return new \FSVendor\WPDesk_Basic_Requirement_Checker($plugin_file, $plugin_name, $text_domain, null, null);
}
/**
* Creates a requirement checker according to given requirements array info.
*
* @param string $plugin_file
* @param string $plugin_name
* @param string $text_domain Text domain to use. If null try to use library text domain.
* @param array $requirements Requirements array as given by plugin.
*
* @return WPDesk_Requirement_Checker
*/
public function create_from_requirement_array($plugin_file, $plugin_name, $requirements, $text_domain = null)
{
$requirements_checker = new \FSVendor\WPDesk_Basic_Requirement_Checker_With_Update_Disable($plugin_file, $plugin_name, $text_domain, $requirements['php'], $requirements['wp'], (bool) \wp_using_ext_object_cache());
if (isset($requirements['plugins'])) {
foreach ($requirements['plugins'] as $requirement) {
$version = isset($requirement['version']) ? $requirement['version'] : null;
$requirements_checker->add_plugin_require($requirement['name'], $requirement['nice_name'], $version);
}
$requirements_checker->transient_delete_on_plugin_version_changed();
}
if (isset($requirements['repo_plugins'])) {
foreach ($requirements['repo_plugins'] as $requirement) {
$requirements_checker->add_plugin_repository_require($requirement['name'], $requirement['version'], $requirement['nice_name']);
}
}
if (isset($requirements['modules'])) {
foreach ($requirements['modules'] as $requirement) {
$requirements_checker->add_php_module_require($requirement['name'], $requirement['nice_name']);
}
}
return $requirements_checker;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace FSVendor;
if (!\class_exists('FSVendor\\WPDesk_Basic_Requirement_Checker')) {
require_once __DIR__ . '/Basic_Requirement_Checker.php';
}
if (!\class_exists('FSVendor\\WPDesk_Basic_Requirement_Checker_With_Update_Disable')) {
/**
* Checks requirements for plugin. When required plugin is updated right now, then say that requirements are not met temporary.
* have to be compatible with PHP 5.2.x
*/
class WPDesk_Basic_Requirement_Checker_With_Update_Disable extends \FSVendor\WPDesk_Basic_Requirement_Checker
{
/**
* Returns true if are requirements are met.
*
* @return bool
*/
public function are_requirements_met()
{
$has_been_met = parent::are_requirements_met();
if (!$has_been_met) {
return $has_been_met;
}
foreach ($this->plugin_require as $name => $plugin_info) {
if ($this->is_currently_updated($name)) {
$nice_name = $plugin_info[self::PLUGIN_INFO_KEY_NICE_NAME];
$this->notices[] = $this->prepare_notice_message(\sprintf(\__('The &#8220;%s&#8221; plugin is temporarily disabled since the required %s plugin is being upgraded.', $this->get_text_domain()), $this->plugin_name, $nice_name, $nice_name));
}
}
return \count($this->notices) === 0;
}
/**
* Is plugin upgrading right now?
*
* @param string $name
*
* @return bool
*/
private function is_currently_updated($name)
{
return isset($_GET['action']) && $_GET['action'] === 'upgrade-plugin' && $_GET['plugin'] === $name;
}
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace FSVendor;
/**
* Checks requirements for plugin
* have to be compatible with PHP 5.2.x
*/
interface WPDesk_Requirement_Checker
{
/**
* @param string $version
*
* @return $this
*/
public function set_min_php_require($version);
/**
* @param string $version
*
* @return $this
*/
public function set_min_wp_require($version);
/**
* @param string $version
*
* @return $this
*/
public function set_min_wc_require($version);
/**
* @param $version
*
* @return $this
*/
public function set_min_openssl_require($version);
/**
* @param string $plugin_name
* @param string $nice_plugin_name Nice plugin name for better looks in notice
*
* @return $this
*/
public function add_plugin_require($plugin_name, $nice_plugin_name = null);
/**
* @param string $module_name
* @param string $nice_name Nice module name for better looks in notice
*
* @return $this
*/
public function add_php_module_require($module_name, $nice_name = null);
/**
* @param string $setting
* @param mixed $value
*
* @return $this
*/
public function add_php_setting_require($setting, $value);
/**
* @return bool
*/
public function are_requirements_met();
/**
* @return void
*/
public function disable_plugin_render_notice();
/**
* @return void
*/
public function render_notices();
/**
* Renders requirement notices in admin panel
*
* @return void
*/
public function disable_plugin();
}

View File

@@ -0,0 +1,17 @@
<?php
namespace FSVendor;
interface WPDesk_Requirement_Checker_Factory
{
/**
* @param $plugin_file
* @param $plugin_name
* @param $text_domain
* @param $php_version
* @param $wp_version
*
* @return WPDesk_Requirement_Checker
*/
public function create_requirement_checker($plugin_file, $plugin_name, $text_domain);
}

View File

@@ -0,0 +1,36 @@
{
"name": "wpdesk\/wp-builder",
"authors": [
{
"name": "Krzysiek",
"email": "krzysiek@wpdesk.pl"
}
],
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit\/phpunit": "<7",
"wp-coding-standards\/wpcs": "^0.14.1",
"squizlabs\/php_codesniffer": "^3.0.2",
"mockery\/mockery": "*",
"10up\/wp_mock": "*",
"wimg\/php-compatibility": "^8"
},
"autoload": {
"psr-4": {
"FSVendor\\WPDesk\\PluginBuilder\\": "src\/"
},
"classmap": [
"src\/Plugin\/WithoutNamespace"
]
},
"autoload-dev": {},
"scripts": {
"phpcs": "phpcs",
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\BuildDirector;
use FSVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
use FSVendor\WPDesk\PluginBuilder\Storage\StorageFactory;
class LegacyBuildDirector
{
/** @var AbstractBuilder */
private $builder;
public function __construct(\FSVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder $builder)
{
$this->builder = $builder;
}
/**
* Builds plugin
*/
public function build_plugin()
{
$this->builder->build_plugin();
$this->builder->init_plugin();
$storage = new \FSVendor\WPDesk\PluginBuilder\Storage\StorageFactory();
$this->builder->store_plugin($storage->create_storage());
}
/**
* Returns built plugin
*
* @return AbstractPlugin
*/
public function get_plugin()
{
return $this->builder->get_plugin();
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Builder;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
use FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
abstract class AbstractBuilder
{
/**
* Create plugin class
*/
public function build_plugin()
{
}
/**
* Store plugin class in some kind of storage
*/
public function store_plugin(\FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
{
}
/**
* Init plugin internal structure
*/
public function init_plugin()
{
}
/**
* Return built plugin
* @return AbstractPlugin
*/
abstract function get_plugin();
/**
* Set settings class in plugin
*
* @param $settings
*/
public function set_settings($settings)
{
}
/**
* Set view class in plugin
*
* @param $view
*/
public function set_view($view)
{
}
/**
* Set tracker class in plugin
*
* @param $tracker
*/
public function set_tracker($tracker)
{
}
/**
* Set helper class in plugin
*
* @param $helper
*/
public function set_helper($helper)
{
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Builder;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
use FSVendor\WPDesk\PluginBuilder\Plugin\ActivationAware;
use FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
/**
* Builder that have info about activations
*
* Warning: We can't extend InfoBuilder.php as some old plugins(without wp-flow) will load the old version od InfoBuilder class that have private plugin property.
*
* @package WPDesk\PluginBuilder\Builder
*/
class InfoActivationBuilder extends \FSVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder
{
const FILTER_PLUGIN_CLASS = 'wp_builder_plugin_class';
const HOOK_BEFORE_PLUGIN_INIT = 'wp_builder_before_plugin_init';
const HOOK_AFTER_PLUGIN_INIT = 'wp_builder_before_init';
/** @var AbstractPlugin */
private $plugin;
/** @var \WPDesk_Buildable */
private $info;
/** @var string */
protected $storage_id;
/**
* @var bool
*/
private $is_active;
/**
* @param \WPDesk_Buildable $info
* @param bool $is_active
*/
public function __construct(\FSVendor\WPDesk_Buildable $info, $is_active)
{
$this->info = $info;
$this->storage_id = $info->get_class_name();
$this->is_active = $is_active;
}
/**
* Builds instance of plugin
*/
public function build_plugin()
{
$class_name = \apply_filters(self::FILTER_PLUGIN_CLASS, $this->info->get_class_name());
/** @var AbstractPlugin $plugin */
$this->plugin = new $class_name($this->info);
if ($this->plugin instanceof \FSVendor\WPDesk\PluginBuilder\Plugin\ActivationAware && $this->is_active) {
$this->plugin->set_active();
}
return $this->plugin;
}
public function store_plugin(\FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
{
$storage->add_to_storage($this->storage_id, $this->plugin);
}
public function init_plugin()
{
\do_action(self::HOOK_BEFORE_PLUGIN_INIT, $this->plugin);
$this->plugin->init();
\do_action(self::HOOK_AFTER_PLUGIN_INIT, $this->plugin);
}
/**
* @return AbstractPlugin
*/
public function get_plugin()
{
return $this->plugin;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Builder;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
use FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage;
/**
* @deprecated Should not be used as some old plugins are using it and we can't touch this.
*
* @package WPDesk\PluginBuilder\Builder
*/
class InfoBuilder extends \FSVendor\WPDesk\PluginBuilder\Builder\AbstractBuilder
{
const FILTER_PLUGIN_CLASS = 'wp_builder_plugin_class';
const HOOK_BEFORE_PLUGIN_INIT = 'wp_builder_before_plugin_init';
const HOOK_AFTER_PLUGIN_INIT = 'wp_builder_before_init';
/** @var AbstractPlugin */
private $plugin;
/** @var \WPDesk_Buildable */
private $info;
/** @var string */
protected $storage_id;
public function __construct(\FSVendor\WPDesk_Buildable $info)
{
$this->info = $info;
$this->storage_id = $info->get_class_name();
}
/**
* Builds instance of plugin
*/
public function build_plugin()
{
$class_name = \apply_filters(self::FILTER_PLUGIN_CLASS, $this->info->get_class_name());
/** @var AbstractPlugin $plugin */
$this->plugin = new $class_name($this->info);
}
public function store_plugin(\FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage $storage)
{
$storage->add_to_storage($this->storage_id, $this->plugin);
}
public function init_plugin()
{
\do_action(self::HOOK_BEFORE_PLUGIN_INIT, $this->plugin);
$this->plugin->init();
\do_action(self::HOOK_AFTER_PLUGIN_INIT, $this->plugin);
}
/**
* @return AbstractPlugin
*/
public function get_plugin()
{
return $this->plugin;
}
}

View File

@@ -0,0 +1,203 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* Base plugin with most basic functionalities used by every WPDesk plugin.
*
*
* Known issues:
*
* The class name is too generic but can't be changed as it would introduce a major incompatibility for most of the plugins.
* The $plugin_url, $docs_url and most other fields should be removed as they only litter the place but for compatibility reasons we can't do it right now.
* Hook methods should be moved to external classes but for compatibility reasons we can't do it right now.
*/
abstract class AbstractPlugin extends \FSVendor\WPDesk\PluginBuilder\Plugin\SlimPlugin
{
/**
* Most info about plugin internals.
*
* @var \WPDesk_Plugin_Info
*/
protected $plugin_info;
/**
* Unique string for this plugin in [a-z_]+ format.
*
* @var string
*/
protected $plugin_namespace;
/**
* Absolute URL to the plugin dir.
*
* @var string
*/
protected $plugin_url;
/**
* Absolute URL to the plugin docs.
*
* @var string
*/
protected $docs_url;
/**
* Absolute URL to the plugin settings url.
*
* @var string
*/
protected $settings_url;
/**
* Support URL.
*
* @var string
*/
protected $support_url;
/**
* AbstractPlugin constructor.
*
* @param \WPDesk_Plugin_Info $plugin_info
*/
public function __construct($plugin_info)
{
$this->plugin_info = $plugin_info;
$this->plugin_namespace = \strtolower($plugin_info->get_plugin_dir());
$this->plugin_url = $this->plugin_info->get_plugin_url();
$this->init_base_variables();
}
/**
* Initialize internal state of the plugin.
*
* @return void
* @deprecated Just use __construct to initialize plugin internal state.
*
*/
public function init_base_variables()
{
}
/**
* Initializes plugin external state.
*
* The plugin internal state is initialized in the constructor and the plugin should be internally consistent after creation.
* The external state includes hooks execution, communication with other plugins, integration with WC etc.
*
* @return void
*/
public function init()
{
$this->hooks();
}
/**
* Returns absolute path to the plugin dir.
*
* @return string
*/
public function get_plugin_file_path()
{
return $this->plugin_info->get_plugin_file_name();
}
/**
* Returns plugin text domain.
*
* @return string
*/
public function get_text_domain()
{
return $this->plugin_info->get_text_domain();
}
/**
* Returns unique string for plugin in [a-z_]+ format. Can be used as plugin id in various places like plugin slug etc.
*
* @return string
*/
public function get_namespace()
{
return $this->plugin_namespace;
}
/**
* Returns plugin absolute URL.
*
* @return string
*/
public function get_plugin_url()
{
return \esc_url(\trailingslashit($this->plugin_url));
}
/**
* Returns plugin absolute URL to dir with front end assets.
*
* @return string
*/
public function get_plugin_assets_url()
{
return \esc_url(\trailingslashit($this->get_plugin_url() . 'assets'));
}
/**
* @return $this
* @deprecated For backward compatibility.
*
*/
public function get_plugin()
{
return $this;
}
/**
* Integrate with WordPress and with other plugins using action/filter system.
*
* @return void
*/
protected function hooks()
{
\add_action('admin_enqueue_scripts', [$this, 'admin_enqueue_scripts']);
\add_action('wp_enqueue_scripts', [$this, 'wp_enqueue_scripts']);
\add_action('plugins_loaded', [$this, 'load_plugin_text_domain']);
\add_filter('plugin_action_links_' . \plugin_basename($this->get_plugin_file_path()), [$this, 'links_filter']);
}
/**
* Initialize plugin test domain. This is a hook function. Do not execute directly.
*
* @return void
*/
public function load_plugin_text_domain()
{
\load_plugin_textdomain($this->get_text_domain(), \false, $this->get_namespace() . '/lang/');
}
/**
* Append JS scripts in the WordPress admin panel. This is a hook function. Do not execute directly.
*
* @return void
*/
public function admin_enqueue_scripts()
{
}
/**
* Append JS scripts in WordPress. This is a hook function. Do not execute directly.
*
* @return void
*/
public function wp_enqueue_scripts()
{
}
/**
* Initialize plugin admin links. This is a hook function. Do not execute directly.
*
* @param string[] $links
*
* @return string[]
*/
public function links_filter($links)
{
$support_link = \get_locale() === 'pl_PL' ? 'https://www.wpdesk.pl/support/' : 'https://www.wpdesk.net/support';
if ($this->support_url) {
$support_link = $this->support_url;
}
$plugin_links = ['<a target="_blank" href="' . $support_link . '">' . \__('Support', $this->get_text_domain()) . '</a>'];
$links = \array_merge($plugin_links, $links);
if ($this->docs_url) {
$plugin_links = ['<a target="_blank" href="' . $this->docs_url . '">' . \__('Docs', $this->get_text_domain()) . '</a>'];
$links = \array_merge($plugin_links, $links);
}
if ($this->settings_url) {
$plugin_links = ['<a href="' . $this->settings_url . '">' . \__('Settings', $this->get_text_domain()) . '</a>'];
$links = \array_merge($plugin_links, $links);
}
return $links;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* Tag the plugin with this ingterface to hook it to the WordPress activation hook.
*
* Note: works from plugin flow ^2.2.
*
* @package WPDesk\PluginBuilder\Plugin
*/
interface Activateable
{
/**
* Plugin activated in WordPress. Do not execute directly.
*
* @return void
*/
public function activate();
}

View File

@@ -0,0 +1,24 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* It means that this class is should know about SUBSCRIPTION activation
*
* @package WPDesk\PluginBuilder\Plugin
*/
interface ActivationAware
{
/**
* Set the activation flag to true
*
* @return void
*/
public function set_active();
/**
* Is subscription active?
*
* @return bool
*/
public function is_active();
}

View File

@@ -0,0 +1,70 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* @deprecated nobody uses it :) And also this library is not a place for this class
*
* @package WPDesk\PluginBuilder\Plugin
*/
class ActivationTracker
{
/**
* Namespace.
*
* @var string
*/
private $namespace;
/**
* ActivationTracker constructor.
*
* @param string $namespace Namespace for settings.
*/
public function __construct($namespace)
{
$this->namespace = $namespace;
}
/**
* Option name for date storage
*
* @return string
*/
private function get_option_name_activation_date()
{
return $this->namespace . '_activation';
}
/**
* Returns activation date and sets it if were not set before
*
* @return int unix timestamp for activation datetime
*/
public function get_activation_date()
{
$activation_date = \get_option($this->get_option_name_activation_date());
if (empty($activation_date)) {
return $this->touch_activation_date();
}
return \intval($activation_date);
}
/**
* Was activation more than two weeks before today
*
* @return bool
*/
public function is_activated_more_than_two_weeks()
{
$two_weeks = 60 * 60 * 24 * 7 * 2;
return $this->get_activation_date() + $two_weeks < \time();
}
/**
* Sets activatiion date for today
*
* @return int unit timestamp for now
*/
public function touch_activation_date()
{
$now = \time();
\update_option($this->get_option_name_activation_date(), $now);
return $now;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* Something that can be instantiated/hooked conditionally.
*
* @see https://github.com/mwpd/basic-scaffold/blob/master/src/Infrastructure/Conditional.php by Alain Schlesser
*
* @package WPDesk\PluginBuilder\Plugin
*/
interface Conditional
{
/**
* Check whether the conditional object is currently needed.
*
* @return bool Whether the conditional object is needed.
*/
public static function is_needed();
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* Tag the plugin with this ingterface to hook it to the WordPress deactivation hook.
*
* Note: works from plugin flow ^2.2.
*
* @package WPDesk\PluginBuilder\Plugin
*/
interface Deactivateable
{
/**
* Plugin deactivate in WordPress. Do not execute directly.
*
* @return void
*/
public function deactivate();
}

View File

@@ -0,0 +1,13 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
interface Hookable
{
/**
* Init hooks (actions and filters).
*
* @return void
*/
public function hooks();
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
interface HookableCollection extends \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* Add hookable object.
*
* @param Hookable|HookablePluginDependant $hookable_object Hookable object.
*/
public function add_hookable(\FSVendor\WPDesk\PluginBuilder\Plugin\Hookable $hookable_object);
/**
* Get hookable instance.
*
* @param string $class_name Class name.
*
* @return false|Hookable
*/
public function get_hookable_instance_by_class_name($class_name);
}

View File

@@ -0,0 +1,57 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
trait HookableParent
{
/**
* Hookable objects.
*
* @var array[Hookable]
*/
private $hookable_objects = array();
/**
* Add hookable object.
*
* @param Hookable|HookablePluginDependant $hookable_object Hookable object.
*/
public function add_hookable(\FSVendor\WPDesk\PluginBuilder\Plugin\Hookable $hookable_object)
{
if ($hookable_object instanceof \FSVendor\WPDesk\PluginBuilder\Plugin\HookablePluginDependant) {
$hookable_object->set_plugin($this);
}
$this->hookable_objects[] = $hookable_object;
}
/**
* Get hookable instance.
*
* @param string $class_name Class name.
*
* @return false|Hookable
*/
public function get_hookable_instance_by_class_name($class_name)
{
foreach ($this->hookable_objects as $hookable_object) {
if ($hookable_object instanceof $class_name) {
return $hookable_object;
}
}
return \false;
}
/**
* Run hooks method on all hookable objects.
*/
protected function hooks_on_hookable_objects()
{
/** @var Hookable $hookable_object $hookable_object */
foreach ($this->hookable_objects as $hookable_object) {
if ($hookable_object instanceof \FSVendor\WPDesk\PluginBuilder\Plugin\Conditional) {
if ($hookable_object::is_needed()) {
$hookable_object->hooks();
}
} else {
$hookable_object->hooks();
}
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
interface HookablePluginDependant extends \FSVendor\WPDesk\PluginBuilder\Plugin\Hookable
{
/**
* Set Plugin.
*
* @param AbstractPlugin $plugin Plugin.
*
* @return null
*/
public function set_plugin(\FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin $plugin);
/**
* Get plugin.
*
* @return AbstractPlugin.
*/
public function get_plugin();
}

View File

@@ -0,0 +1,34 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* @package WPDesk\PluginBuilder\Plugin
*/
trait PluginAccess
{
/**
* Plugin.
*
* @var AbstractPlugin
*/
private $plugin;
/**
* Set plugin.
*
* @param AbstractPlugin $plugin Plugin.
*/
public function set_plugin(\FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin $plugin)
{
$this->plugin = $plugin;
}
/**
* Get plugin.
*
* @return AbstractPlugin
*/
public function get_plugin()
{
return $this->plugin;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* Most clean plugin class with only most important details.
*/
abstract class SlimPlugin implements \FSVendor\WPDesk_Translatable
{
/**
* Initializes plugin external state.
*
* The plugin internal state is initialized in the constructor and the plugin should be internally consistent after creation.
* The external state includes hooks execution, communication with other plugins, integration with WC etc.
*
* @return void
*/
public abstract function init();
}

View File

@@ -0,0 +1,63 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Plugin;
/**
* @deprecated Use wpdesk/wp-view
*
* @package WPDesk\PluginBuilder\Plugin
*/
trait TemplateLoad
{
/**
* Plugin path.
*
* @var string
*/
protected $plugin_path;
/**
* Template path.
*
* @var string
*/
protected $template_path;
/**
* Init base variables for plugin
*/
public function init_template_base_variables()
{
$this->plugin_path = $this->plugin_info->get_plugin_dir();
$this->template_path = $this->plugin_info->get_text_domain();
}
/**
* Renders end returns selected template
*
* @param string $name Name of the template.
* @param string $path Additional inner path to the template.
* @param array $args args Accessible from template.
*
* @return string
*/
public function load_template($name, $path = '', $args = array())
{
$plugin_template_path = \trailingslashit($this->plugin_path) . 'templates/';
// Look within passed path within the theme - this is priority.
$template = \locate_template(array(\trailingslashit($this->get_template_path()) . \trailingslashit($path) . $name . '.php'));
if (!$template) {
$template = $plugin_template_path . \trailingslashit($path) . $name . '.php';
}
\extract($args);
\ob_start();
include $template;
return \ob_get_clean();
}
/**
* Get template path.
*
* @return string
*/
public function get_template_path()
{
return \trailingslashit($this->template_path);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace FSVendor;
/**
* Have info about what class should be built by WPDesk_Builder
*
* have to be compatible with PHP 5.2.x
*/
interface WPDesk_Buildable
{
/** @return string */
public function get_class_name();
}

View File

@@ -0,0 +1,27 @@
<?php
namespace FSVendor;
if (!\interface_exists('FSVendor\\WPDesk_Translatable')) {
require_once __DIR__ . '/Translatable.php';
}
/**
* Have MUST HAVE info for plugin instantion
*
* have to be compatible with PHP 5.2.x
*/
interface WPDesk_Has_Plugin_Info extends \FSVendor\WPDesk_Translatable
{
/**
* @return string
*/
public function get_plugin_file_name();
/**
* @return string
*/
public function get_plugin_dir();
/**
* @return string
*/
public function get_version();
}

View File

@@ -0,0 +1,190 @@
<?php
namespace FSVendor;
if (!\interface_exists('FSVendor\\WPDesk_Translatable')) {
require_once __DIR__ . '/Translatable.php';
}
if (!\interface_exists('FSVendor\\WPDesk_Buildable')) {
require_once __DIR__ . '/Buildable.php';
}
if (!\interface_exists('FSVendor\\WPDesk_Has_Plugin_Info')) {
require_once __DIR__ . '/Has_Plugin_Info.php';
}
/**
* Structure with core info about plugin
*
* have to be compatible with PHP 5.2.x
*/
class WPDesk_Plugin_Info implements \FSVendor\WPDesk_Translatable, \FSVendor\WPDesk_Buildable, \FSVendor\WPDesk_Has_Plugin_Info
{
/** @var string */
private $plugin_file_name;
/** @var string */
private $plugin_dir;
/** @var string */
private $plugin_url;
/** @var string */
private $class_name;
/** @var string */
private $version;
/** @var string */
private $product_id;
/** @var string */
private $plugin_name;
/** @var \DateTimeInterface */
private $release_date;
/** string */
private $text_domain;
/**
* @var array
*/
private $plugin_shops;
/**
* @return string
*/
public function get_plugin_file_name()
{
return $this->plugin_file_name;
}
/**
* @param string $plugin_name
*/
public function set_plugin_file_name($plugin_name)
{
$this->plugin_file_name = $plugin_name;
}
/**
* @return string
*/
public function get_plugin_dir()
{
return $this->plugin_dir;
}
/**
* @param string $plugin_dir
*/
public function set_plugin_dir($plugin_dir)
{
$this->plugin_dir = $plugin_dir;
}
/**
* @return string
*/
public function get_plugin_url()
{
return $this->plugin_url;
}
/**
* @param string $plugin_url
*/
public function set_plugin_url($plugin_url)
{
$this->plugin_url = $plugin_url;
}
/**
* @return string
*/
public function get_version()
{
return $this->version;
}
/**
* @param string $version
*/
public function set_version($version)
{
$this->version = $version;
}
/**
* @return string
*/
public function get_product_id()
{
return $this->product_id;
}
/**
* @param string $product_id
*/
public function set_product_id($product_id)
{
$this->product_id = $product_id;
}
/**
* @return string
*/
public function get_plugin_name()
{
return $this->plugin_name;
}
/**
* @param string $plugin_name
*/
public function set_plugin_name($plugin_name)
{
$this->plugin_name = $plugin_name;
}
/**
* @return DateTimeInterface
*/
public function get_release_date()
{
return $this->release_date;
}
/**
* @param \DateTimeInterface $release_date
*/
public function set_release_date($release_date)
{
$this->release_date = $release_date;
}
/**
* @return string
*/
public function get_class_name()
{
return $this->class_name;
}
/**
* @param string $class_name
*/
public function set_class_name($class_name)
{
$this->class_name = $class_name;
}
/**
* @return string
*/
public function get_text_domain()
{
return $this->text_domain;
}
/**
* @param $value
*/
public function set_text_domain($value)
{
$this->text_domain = $value;
}
/**
* @return array
*/
public function get_plugin_shops()
{
return $this->plugin_shops;
}
/**
* @param array $plugin_shops
*/
public function set_plugin_shops($plugin_shops)
{
$this->plugin_shops = $plugin_shops;
}
/**
* @return string
*/
public function get_plugin_slug()
{
return \basename($this->get_plugin_dir());
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace FSVendor;
/**
* @deprecated Have typo so better use WPDesk_Translatable
*/
interface WPDesk_Translable
{
/** @return string */
public function get_text_domain();
}

View File

@@ -0,0 +1,17 @@
<?php
namespace FSVendor;
if (!\interface_exists('FSVendor\\WPDesk_Translable')) {
require_once 'Translable.php';
}
/**
* Have info about textdomain - how to translate texts
*
* have to be compatible with PHP 5.2.x
*/
interface WPDesk_Translatable extends \FSVendor\WPDesk_Translable
{
/** @return string */
public function get_text_domain();
}

View File

@@ -0,0 +1,7 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage\Exception;
class ClassAlreadyExists extends \RuntimeException
{
}

View File

@@ -0,0 +1,7 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage\Exception;
class ClassNotExists extends \RuntimeException
{
}

View File

@@ -0,0 +1,19 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
interface PluginStorage
{
/**
* @param string $class
* @param AbstractPlugin $object
*/
public function add_to_storage($class, $object);
/**
* @param string $class
*
* @return AbstractPlugin
*/
public function get_from_storage($class);
}

View File

@@ -0,0 +1,37 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
/**
* Can store plugin instances in static variable
*
* @package WPDesk\PluginBuilder\Storage
*/
class StaticStorage implements \FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage
{
protected static $instances = [];
/**
* @param string $class
* @param AbstractPlugin $object
*/
public function add_to_storage($class, $object)
{
if (isset(self::$instances[$class])) {
throw new \FSVendor\WPDesk\PluginBuilder\Storage\Exception\ClassAlreadyExists("Class {$class} already exists");
}
self::$instances[$class] = $object;
}
/**
* @param string $class
*
* @return AbstractPlugin
*/
public function get_from_storage($class)
{
if (isset(self::$instances[$class])) {
return self::$instances[$class];
}
throw new \FSVendor\WPDesk\PluginBuilder\Storage\Exception\ClassNotExists("Class {$class} not exists in storage");
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage;
class StorageFactory
{
/**
* @return PluginStorage
*/
public function create_storage()
{
return new \FSVendor\WPDesk\PluginBuilder\Storage\WordpressFilterStorage();
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace FSVendor\WPDesk\PluginBuilder\Storage;
use FSVendor\WPDesk\PluginBuilder\Plugin\AbstractPlugin;
/**
* Can store plugin instances in WordPress filter system.
*
* @package WPDesk\PluginBuilder\Storage
*/
class WordpressFilterStorage implements \FSVendor\WPDesk\PluginBuilder\Storage\PluginStorage
{
const STORAGE_FILTER_NAME = 'wpdesk_plugin_instances';
/**
* @param string $class
* @param AbstractPlugin $object
*/
public function add_to_storage($class, $object)
{
\add_filter(self::STORAGE_FILTER_NAME, static function ($plugins) use($class, $object) {
if (isset($plugins[$class])) {
throw new \FSVendor\WPDesk\PluginBuilder\Storage\Exception\ClassAlreadyExists("Class {$class} already exists");
}
$plugins[$class] = $object;
return $plugins;
});
}
/**
* @param string $class
*
* @return AbstractPlugin
*/
public function get_from_storage($class)
{
$plugins = \apply_filters(self::STORAGE_FILTER_NAME, []);
if (isset($plugins[$class])) {
return $plugins[$class];
}
throw new \FSVendor\WPDesk\PluginBuilder\Storage\Exception\ClassNotExists("Class {$class} not exists in storage");
}
}

View File

@@ -0,0 +1,50 @@
{
"name": "wpdesk\/wp-forms",
"description": "WP Forms",
"authors": [
{
"name": "Marcin",
"email": "marcin@wpdesk.pl"
},
{
"name": "Krzysiek",
"email": "krzysiek@wpdesk.pl"
},
{
"name": "Piotr Potrebka",
"email": "piotr.potrebka@wpdesk.pl"
}
],
"require": {
"php": ">=5.6",
"ext-curl": "*",
"ext-json": "*",
"wpdesk\/wp-persistence": "^2.0|^3.0",
"wpdesk\/wp-view": "^2"
},
"require-dev": {
"phpunit\/phpunit": "<7",
"mockery\/mockery": "*",
"10up\/wp_mock": "*",
"wpdesk\/wp-code-sniffer": "^1.2.3"
},
"autoload": {
"psr-4": {
"FSVendor\\WPDesk\\Forms\\": "src\/"
}
},
"autoload-dev": {},
"extra": {
"text-domain": "wp-forms",
"translations-folder": "lang",
"po-files": {
"pl_PL": "pl_PL.po"
}
},
"scripts": {
"phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never",
"phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage",
"phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never",
"phpunit-integration-fast": "phpunit --configuration phpunit-integration.xml --no-coverage"
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace FSVendor\WPDesk\Forms;
use Psr\Container\ContainerInterface;
use FSVendor\WPDesk\Persistence\PersistentContainer;
/**
* Persistent container support for forms.
*
* @package WPDesk\Forms
*/
interface ContainerForm
{
/**
* @param ContainerInterface $data
*
* @return void
*/
public function set_data($data);
/**
* Put data from form into a container.
*
* @param PersistentContainer $container Target container.
*
* @return void
*/
public function put_data(\FSVendor\WPDesk\Persistence\PersistentContainer $container);
}

View File

@@ -0,0 +1,13 @@
<?php
namespace FSVendor\WPDesk\Forms;
interface Escaper
{
/**
* @param mixed $value
*
* @return string
*/
public function escape($value);
}

View File

@@ -0,0 +1,134 @@
<?php
namespace FSVendor\WPDesk\Forms;
use FSVendor\WPDesk\Forms\Field\BasicField;
/**
* The idea is that from the moment the factory returns this interface it's values cannot be changed.
* And that is why here are only the getters.
*
* The: Validation, Serialization, Sanitization features are provided trough delegated classes (get_validator, get_serializer ...)
*
* @package WPDesk\Forms
*/
interface Field
{
/** @return string */
public function get_name();
/** @return mixed */
public function get_default_value();
/** @return string */
public function get_template_name();
/**
* When this field is used on form this field will force it's own template.
*
* return bool
*/
public function should_override_form_template();
/**
* HTML label.
*
* @return string
*/
public function get_label();
/** bool */
public function has_label();
/**
* Description for field. It can be shown near the field.
*
* @return string
*/
public function get_description();
/**
* Additional field description that should be shown in optional hover tip.
*
* @return string
*/
public function get_description_tip();
/** @return bool */
public function has_description_tip();
/** @return bool */
public function has_description();
/**
* @return bool
*/
public function is_readonly();
/** @return bool */
public function is_disabled();
/** @return string */
public function get_id();
/** @bool */
public function is_required();
/** @return bool */
public function has_placeholder();
/** @return string */
public function get_placeholder();
/**
* @param string[] $except
*
* @return string[] name->value
*/
public function get_attributes($except = []);
/**
* @param string $name
* @param string $default
*
* @return string
*/
public function get_attribute($name, $default = null);
/** @return bool */
public function is_attribute_set($name);
/**
* @param string $name
*
* @return string
*/
public function get_meta_value($name);
/** @return bool */
public function is_meta_value_set($name);
/**
* @return string
*/
public function get_classes();
/** bool */
public function has_classes();
/** @return bool */
public function is_class_set($name);
/** bool */
public function has_data();
/**
* @return array
*/
public function get_data();
/**
* @param string $data_name
* @param string $data_value
*
* @return $this
*/
public function add_data($data_name, $data_value);
/**
* @param string $data_name
*
* @return $this
*/
public function unset_data($data_name);
/**
* @return mixed
*/
public function get_possible_values();
/**
* @return bool
*/
public function is_multiple();
/**
* @return Validator
*/
public function get_validator();
/**
* @return Sanitizer
*/
public function get_sanitizer();
/** @return Serializer */
public function get_serializer();
}

View File

@@ -0,0 +1,283 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\NoSanitize;
use FSVendor\WPDesk\Forms\Serializer;
use FSVendor\WPDesk\Forms\Serializer\NoSerialize;
use FSVendor\WPDesk\Forms\Validator\ChainValidator;
use FSVendor\WPDesk\Forms\Validator\RequiredValidator;
/**
* Base class for fields. Is responsible for settings all required field values and provides standard implementation for
* the field interface.
*
* @package WPDesk\Forms
*/
abstract class BasicField implements \FSVendor\WPDesk\Forms\Field
{
use Field\Traits\HtmlAttributes;
/** @var array[] */
protected $meta;
protected $default_value;
public function __construct()
{
$this->meta['class'] = [];
}
public function get_label()
{
return $this->meta['label'];
}
/**
* @param string $value
*
* @return $this
*/
public function set_label($value)
{
$this->meta['label'] = $value;
return $this;
}
public function get_description_tip()
{
return $this->meta['description_tip'];
}
public function has_description_tip()
{
return isset($this->meta['description_tip']);
}
public function should_override_form_template()
{
return isset($this->attributes['overrite_template']) ? $this->attributes['overrite_template'] : \false;
}
public function get_description()
{
return $this->meta['description'];
}
public function has_label()
{
return isset($this->meta['label']);
}
public function has_description()
{
return isset($this->meta['description']);
}
public function set_description($value)
{
$this->meta['description'] = $value;
return $this;
}
public function set_description_tip($value)
{
$this->meta['description_tip'] = $value;
return $this;
}
/**
* @return array
*
* @deprecated not sure if needed. TODO: Check later.
*/
public function get_type()
{
return $this->attributes['type'];
}
/**
* @param string $value
*
* @return $this
*/
public function set_placeholder($value)
{
$this->meta['placeholder'] = $value;
return $this;
}
public function has_placeholder()
{
return isset($this->meta['placeholder']);
}
public function get_placeholder()
{
return $this->meta['placeholder'];
}
/**
* @param string $name
*
* @return $this
*/
public function set_name($name)
{
$this->attributes['name'] = $name;
return $this;
}
public function get_meta_value($name)
{
return $this->meta[$name];
}
public function get_classes()
{
return \implode(' ', $this->meta['class']);
}
public function has_classes()
{
return !empty($this->meta['class']);
}
public function has_data()
{
return !empty($this->meta['data']);
}
/**
* @return array
*/
public function get_data()
{
return empty($this->meta['data']) ? [] : $this->meta['data'];
}
public function get_possible_values()
{
return isset($this->meta['possible_values']) ? $this->meta['possible_values'] : [];
}
public function get_id()
{
return isset($this->attributes['id']) ? $this->attributes['id'] : \sanitize_title($this->get_name());
}
public function get_name()
{
return $this->attributes['name'];
}
public function is_multiple()
{
return isset($this->attributes['multiple']) ? $this->attributes['multiple'] : \false;
}
/**
* @return $this
*/
public function set_disabled()
{
$this->attributes['disabled'] = \true;
return $this;
}
public function is_disabled()
{
return isset($this->attributes['disabled']) ? $this->attributes['disabled'] : \false;
}
/**
* @return $this
*/
public function set_readonly()
{
$this->attributes['readonly'] = \true;
return $this;
}
public function is_readonly()
{
return isset($this->attributes['readonly']) ? $this->attributes['readonly'] : \false;
}
/**
* @return $this
*/
public function set_required()
{
$this->meta['required'] = \true;
return $this;
}
/**
* @param string $class_name
*
* @return $this
*/
public function add_class($class_name)
{
$this->meta['class'][$class_name] = $class_name;
return $this;
}
/**
* @param string $class_name
*
* @return $this
*/
public function unset_class($class_name)
{
unset($this->meta['class'][$class_name]);
return $this;
}
/**
* @param string $data_name
* @param string $data_value
*
* @return $this
*/
public function add_data($data_name, $data_value)
{
if (!isset($this->meta['data'])) {
$this->meta['data'] = [];
}
$this->meta['data'][$data_name] = $data_value;
return $this;
}
/**
* @param string $data_name
*
* @return $this
*/
public function unset_data($data_name)
{
unset($this->meta['data'][$data_name]);
return $this;
}
public function is_meta_value_set($name)
{
return isset($this->meta[$name]);
}
public function is_class_set($name)
{
return isset($this->meta['class'][$name]);
}
public function get_default_value()
{
return $this->default_value;
}
/**
* @param string $value
*
* @return $this
*/
public function set_default_value($value)
{
$this->default_value = $value;
return $this;
}
/**
* @return ChainValidator
*/
public function get_validator()
{
$chain = new \FSVendor\WPDesk\Forms\Validator\ChainValidator();
if ($this->is_required()) {
$chain->attach(new \FSVendor\WPDesk\Forms\Validator\RequiredValidator());
}
return $chain;
}
public function is_required()
{
return isset($this->meta['required']) ? $this->meta['required'] : \false;
}
public function get_sanitizer()
{
return new \FSVendor\WPDesk\Forms\Sanitizer\NoSanitize();
}
/**
* @return Serializer
*/
public function get_serializer()
{
if (isset($this->meta['serializer']) && $this->meta['serializer'] instanceof \FSVendor\WPDesk\Forms\Serializer) {
return $this->meta['serializer'];
}
return new \FSVendor\WPDesk\Forms\Serializer\NoSerialize();
}
public function set_serializer(\FSVendor\WPDesk\Forms\Serializer $serializer)
{
$this->meta['serializer'] = $serializer;
return $this;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class ButtonField extends \FSVendor\WPDesk\Forms\Field\NoValueField
{
public function get_template_name()
{
return 'button';
}
public function get_type()
{
return 'button';
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class CheckboxField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
const VALUE_TRUE = 'yes';
const VALUE_FALSE = 'no';
public function __construct()
{
parent::__construct();
$this->set_attribute('type', 'checkbox');
}
public function get_template_name()
{
return 'input-checkbox';
}
public function get_sublabel()
{
return $this->meta['sublabel'];
}
public function set_sublabel($value)
{
$this->meta['sublabel'] = $value;
return $this;
}
public function has_sublabel()
{
return isset($this->meta['sublabel']);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer;
class DateField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_placeholder('YYYY-MM-DD');
}
public function get_type()
{
return 'date';
}
public function get_template_name()
{
return 'input-text';
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer;
class DatePickerField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
$this->add_class('date-picker');
$this->set_placeholder('YYYY-MM-DD');
$this->set_attribute('type', 'text');
}
public function get_sanitizer()
{
return new \FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer();
}
public function get_template_name()
{
return 'input-date-picker';
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class Header extends \FSVendor\WPDesk\Forms\Field\NoValueField
{
public function __construct()
{
parent::__construct();
$this->meta['header_size'] = '';
}
public function get_template_name()
{
return 'header';
}
public function should_override_form_template()
{
return \true;
}
public function set_header_size($value)
{
$this->meta['header_size'] = $value;
return $this;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer;
class HiddenField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
$this->set_attribute('type', 'hidden');
}
public function get_sanitizer()
{
return new \FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer();
}
public function get_template_name()
{
return 'input-hidden';
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class ImageInputField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
$this->set_attribute('type', 'text');
}
/**
* @return string
*/
public function get_template_name()
{
return 'input-image';
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer;
class InputNumberField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
$this->set_attribute('type', 'number');
}
public function get_sanitizer()
{
return new \FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer();
}
public function get_template_name()
{
return 'input-number';
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer;
class InputTextField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
$this->set_attribute('type', 'text');
}
public function get_sanitizer()
{
return new \FSVendor\WPDesk\Forms\Sanitizer\TextFieldSanitizer();
}
public function get_template_name()
{
return 'input-text';
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class MultipleInputTextField extends \FSVendor\WPDesk\Forms\Field\InputTextField
{
/**
* @return string
*/
public function get_template_name()
{
return 'input-text-multiple';
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\Validator\NonceValidator;
class NoOnceField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct($action_name)
{
parent::__construct();
$this->meta['action'] = $action_name;
}
public function get_validator()
{
return new \FSVendor\WPDesk\Forms\Validator\NonceValidator($this->get_meta_value('action'));
}
public function get_template_name()
{
return 'noonce';
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
/**
* Base class for Fields that can show itself on form but cannot process any value.
*
* @package WPDesk\Forms
*/
abstract class NoValueField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function get_name()
{
return '';
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class Paragraph extends \FSVendor\WPDesk\Forms\Field\NoValueField
{
public function get_template_name()
{
return 'paragraph';
}
public function should_override_form_template()
{
return \true;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class ProductSelect extends \FSVendor\WPDesk\Forms\Field\SelectField
{
public function __construct()
{
parent::__construct();
$this->set_multiple();
}
public function get_template_name()
{
return 'product-select';
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class RadioField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function get_template_name()
{
return 'input-radio';
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class SelectField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function get_template_name()
{
return 'select';
}
public function set_options($options)
{
$this->meta['possible_values'] = $options;
return $this;
}
public function set_multiple()
{
$this->attributes['multiple'] = \true;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class SubmitField extends \FSVendor\WPDesk\Forms\Field\NoValueField
{
public function get_template_name()
{
return 'input-submit';
}
public function get_type()
{
return 'submit';
}
public function should_override_form_template()
{
return \true;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class TextAreaField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
}
public function get_template_name()
{
return 'textarea';
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class TimepickerField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
/**
* @inheritDoc
*/
public function get_template_name()
{
return 'timepicker';
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace FSVendor\WPDesk\Forms\Field\Traits;
/**
* Implementation of HTML attributes like id, name, action etc.
*
* @package WPDesk\Forms\Field\Traits
*/
trait HtmlAttributes
{
/** @var string[] */
protected $attributes;
/**
* Get list of all attributes except given.
*
* @param string[] $except
*
* @return string[]
*/
public function get_attributes($except = ['name', 'type'])
{
return \array_filter($this->attributes, function ($value, $key) use($except) {
return !\in_array($key, $except, \true);
}, \ARRAY_FILTER_USE_BOTH);
}
/**
* @param string $name
* @param string $value
*
* @return $this
*/
public function set_attribute($name, $value)
{
$this->attributes[$name] = $value;
return $this;
}
/**
* @param string $name
*
* @return $this
*/
public function unset_attribute($name)
{
unset($this->attributes[$name]);
return $this;
}
/**
* @param string $name
*
* @return bool
*/
public function is_attribute_set($name)
{
return isset($this->attributes[$name]);
}
/**
* @param string $name
* @param mixed $default
*
* @return string
*/
public function get_attribute($name, $default = null)
{
return $this->attributes[$name] ?? $default;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class WooSelect extends \FSVendor\WPDesk\Forms\Field\SelectField
{
public function __construct()
{
parent::__construct();
$this->set_multiple();
$this->add_class('wc-enhanced-select');
}
public function get_template_name()
{
return 'woo-select';
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace FSVendor\WPDesk\Forms\Field;
class WyswigField extends \FSVendor\WPDesk\Forms\Field\BasicField
{
public function __construct()
{
parent::__construct();
$this->set_default_value('');
}
public function get_template_name()
{
return 'wyswig';
}
public function should_override_form_template()
{
return \true;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms;
/**
* FieldProvider is owner of FormFields. These fields can be used to render forms and process values.
*/
interface FieldProvider
{
/**
* Returns owned fields.
*
* @return Field[]
*/
public function get_fields();
}

View File

@@ -0,0 +1,18 @@
<?php
namespace FSVendor\WPDesk\Forms;
/**
* @class FieldRenderer
*/
interface FieldRenderer
{
/**
* @param FieldProvider $provider
* @param array $fields_data
* @param string $name_prefix
*
* @return string|array String or normalized array
*/
public function render_fields(\FSVendor\WPDesk\Forms\FieldProvider $provider, array $fields_data, $name_prefix = '');
}

View File

@@ -0,0 +1,22 @@
<?php
namespace FSVendor\WPDesk\Forms;
use Psr\Container\ContainerInterface;
/**
* Some field owners can receive and process field data.
* Probably should be used with FieldProvider interface.
*
* @package WPDesk\Forms
*/
interface FieldsDataReceiver
{
/**
* Set values corresponding to fields.
*
* @param ContainerInterface $data
*
* @return void
*/
public function update_fields_data(\Psr\Container\ContainerInterface $data);
}

View File

@@ -0,0 +1,71 @@
<?php
namespace FSVendor\WPDesk\Forms;
use FSVendor\WPDesk\View\Renderer\Renderer;
/**
* Abstraction layer for forms.
*
* @package WPDesk\Forms
*/
interface Form
{
/**
* For some reason you may want to disable a form. Returns false when disabled.
*
* @return bool
*/
public function is_active();
/**
* Whether form handle_request method was successfully executed.
*
* @return bool
*/
public function is_submitted();
/**
* After handle_request or set_data the data in form can be invalid according to field validators.
* Returns false when onle of them says the data is invalid.
*
* @return bool
*/
public function is_valid();
/**
* Add array to update data.
*
* @param array $request New data to update.
*/
public function handle_request($request = array());
/**
* Data could be saved in some place. Use this method to transmit them to form.
*
* @param array $data Data for form.
*/
public function set_data($data);
/**
* Use to render the form to string.
*
* @param Renderer $renderer Renderer to render form fields and form-templates.
*
* @return string
*/
public function render_form(\FSVendor\WPDesk\View\Renderer\Renderer $renderer);
/**
* Get data from form. Use after handle_request or set_data.
*
* @return array
*/
public function get_data();
/**
* Get data from form. Use after handle_request or set_data.
* The difference get_data is that here you will not get any objects and complex data types besides arrays.
*
* @return array
*/
public function get_normalized_data();
/**
* Form if you ever need to have more than one form at once.
*
* @return string
*/
public function get_form_id();
}

View File

@@ -0,0 +1,81 @@
<?php
namespace FSVendor\WPDesk\Forms\Form;
/**
* Old abstraction layer for forms.
*
* @package WPDesk\Forms
*
* @deprecated Use ony for backward compatibility with Forms 1.x
*/
abstract class AbstractForm
{
/**
* Unique form_id.
*
* @var string
*/
protected $form_id = 'form';
/**
* Updated data.
*
* @var array
*/
protected $updated_data = array();
/**
* Checks if form should be active.
*
* @return bool
*/
public function is_active()
{
return \true;
}
/**
* Create form data and return an associative array.
*
* @return array
*/
protected abstract function create_form_data();
/**
* Add array to update data.
*
* @param array $new_data new data to update.
*/
public function update_form_data(array $new_data = array())
{
$this->updated_data = $new_data;
}
/**
* Merge created and updated data and return associative array. Add to all keys form prefix.
*
* @return array
*/
public function get_form_data()
{
return \array_merge($this->create_form_data(), $this->updated_data);
}
/**
* Get prefixed array returns array with prefixed form_id
*
* @return array
*/
public function get_prefixed_form_data()
{
$array = $this->get_form_data();
$form_id = $this->get_form_id();
return \array_combine(\array_map(function ($k) use($form_id) {
return $form_id . '_' . $k;
}, \array_keys($array)), $array);
}
/**
* return form Id
*
* @return string
*/
public function get_form_id()
{
return $this->form_id;
}
}

View File

@@ -0,0 +1,246 @@
<?php
namespace FSVendor\WPDesk\Forms\Form;
use Psr\Container\ContainerInterface;
use FSVendor\WPDesk\Forms\ContainerForm;
use FSVendor\WPDesk\Forms\Field;
use FSVendor\WPDesk\Forms\FieldProvider;
use FSVendor\WPDesk\Forms\Form;
use FSVendor\WPDesk\Persistence\Adapter\ArrayContainer;
use FSVendor\WPDesk\Persistence\ElementNotExistsException;
use FSVendor\WPDesk\Persistence\PersistentContainer;
use FSVendor\WPDesk\View\Renderer\Renderer;
class FormWithFields implements \FSVendor\WPDesk\Forms\Form, \FSVendor\WPDesk\Forms\ContainerForm, \FSVendor\WPDesk\Forms\FieldProvider
{
use Field\Traits\HtmlAttributes;
/**
* Unique form_id.
*
* @var string
*/
protected $form_id = 'form';
/**
* Updated data.
*
* @var array
*/
private $updated_data;
/**
* Form fields.
*
* @var Field[]
*/
private $fields;
/**
* FormWithFields constructor.
*
* @param array $fields Form fields.
* @param string $form_id Unique form id.
*/
public function __construct(array $fields, $form_id = 'form')
{
$this->fields = $fields;
$this->form_id = $form_id;
$this->updated_data = null;
}
/**
* Set Form action attribute.
*
* @param string $action
*/
public function set_action($action)
{
$this->attributes['action'] = $action;
return $this;
}
/**
* Set Form method attribute ie. GET/POST.
*
* @param string $method
*/
public function set_method($method)
{
$this->attributes['method'] = $method;
return $this;
}
/**
* @return string
*/
public function get_method()
{
return isset($this->attributes['method']) ? $this->attributes['method'] : 'POST';
}
/**
* @return string
*/
public function get_action()
{
return isset($this->attributes['action']) ? $this->attributes['action'] : '';
}
/**
* @inheritDoc
*/
public function is_submitted()
{
return null !== $this->updated_data;
}
/**
* @inheritDoc
*/
public function add_field(\FSVendor\WPDesk\Forms\Field $field)
{
$this->fields[] = $field;
}
/**
* @inheritDoc
*/
public function is_active()
{
return \true;
}
/**
* Add more fields to form.
*
* @param Field[] $fields Field to add to form.
*/
public function add_fields(array $fields)
{
\array_map([$this, 'add_field'], $fields);
}
/**
* @inheritDoc
*/
public function is_valid()
{
foreach ($this->fields as $field) {
$field_value = isset($this->updated_data[$field->get_name()]) ? $this->updated_data[$field->get_name()] : $field->get_default_value();
$field_validator = $field->get_validator();
if (!$field_validator->is_valid($field_value)) {
return \false;
}
}
return \true;
}
/**
* Add array to update data.
*
* @param array|ContainerInterface $request new data to update.
*/
public function handle_request($request = array())
{
if ($this->updated_data === null) {
$this->updated_data = [];
}
foreach ($this->fields as $field) {
$data_key = $field->get_name();
if (isset($request[$data_key])) {
$this->updated_data[$data_key] = $field->get_sanitizer()->sanitize($request[$data_key]);
}
}
}
/**
* Data could be saved in some place. Use this method to transmit them to form.
*
* @param array|ContainerInterface $data Data consistent with Form and ContainerForm interface.
*/
public function set_data($data)
{
if (\is_array($data)) {
$data = new \FSVendor\WPDesk\Persistence\Adapter\ArrayContainer($data);
}
foreach ($this->fields as $field) {
$data_key = $field->get_name();
if ($data->has($data_key)) {
try {
$this->updated_data[$data_key] = $data->get($data_key);
} catch (\FSVendor\WPDesk\Persistence\ElementNotExistsException $e) {
$this->updated_data[$data_key] = \false;
}
}
}
}
/**
* Renders only fields without form.
*
* @param Renderer $renderer
*
* @return string
*/
public function render_fields(\FSVendor\WPDesk\View\Renderer\Renderer $renderer)
{
$content = '';
$fields_data = $this->get_data();
foreach ($this->get_fields() as $field) {
$content .= $renderer->render($field->should_override_form_template() ? $field->get_template_name() : 'form-field', ['field' => $field, 'renderer' => $renderer, 'name_prefix' => $this->get_form_id(), 'value' => isset($fields_data[$field->get_name()]) ? $fields_data[$field->get_name()] : $field->get_default_value(), 'template_name' => $field->get_template_name()]);
}
return $content;
}
/**
* @inheritDoc
*/
public function render_form(\FSVendor\WPDesk\View\Renderer\Renderer $renderer)
{
$content = $renderer->render('form-start', [
'form' => $this,
'method' => $this->get_method(),
// backward compat
'action' => $this->get_action(),
]);
$content .= $this->render_fields($renderer);
$content .= $renderer->render('form-end');
return $content;
}
/**
* @inheritDoc
*/
public function put_data(\FSVendor\WPDesk\Persistence\PersistentContainer $container)
{
foreach ($this->get_fields() as $field) {
$data_key = $field->get_name();
if (empty($data_key)) {
continue;
}
if (!isset($this->updated_data[$data_key])) {
$container->set($data_key, $field->get_default_value());
} else {
$container->set($data_key, $this->updated_data[$data_key]);
}
}
}
/**
* @inheritDoc
*/
public function get_data()
{
$data = $this->updated_data;
foreach ($this->get_fields() as $field) {
$data_key = $field->get_name();
if (!isset($data[$data_key])) {
$data[$data_key] = $field->get_default_value();
}
}
return $data;
}
/**
* @inheritDoc
*/
public function get_fields()
{
return $this->fields;
}
/**
* @inheritDoc
*/
public function get_form_id()
{
return $this->form_id;
}
/**
* @inheritDoc
*/
public function get_normalized_data()
{
return $this->get_data();
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace FSVendor\WPDesk\Forms\Form;
use FSVendor\WPDesk\Forms\Form;
/**
* FormsCollection class store AbstractForm instances and merges forms data from all collections
*
* @deprecated Use ony for backward compatibility with Forms 1.x
*
* @package WPDesk\Forms
*/
class FormsCollection
{
/**
* AbstractForm array collection.
*
* @var Form[]
*/
protected $forms = array();
/**
* Unique form_id.
*
* @var string
*/
protected $form_id = 'form';
/**
* Updated data.
*
* @var array
*/
protected $updated_data = array();
/**
* Add forms. All keys in this array must be unique, otherwise add_form will throw exception.
*
* @param Form[] $forms
*/
public function add_forms(array $forms = array())
{
foreach ($forms as $form_object) {
$this->add_form($form_object);
}
}
/**
* Add form. If key is not unique throw exception.
*
* @param Form $form
*
* @throws \OutOfBoundsException
*/
public function add_form(\FSVendor\WPDesk\Forms\Form\AbstractForm $form)
{
if (!$this->is_form_exists($form->get_form_id())) {
$this->forms[$form->get_form_id()] = $form;
} else {
throw new \OutOfBoundsException('Form with this key already exists');
}
}
/**
* Is form exists. Checks if key exists in the array of forms and return bool.
*
* @param string $form_id
*
* @return bool
*/
public function is_form_exists($form_id)
{
return isset($this->forms[(string) $form_id]);
}
/**
* Get form.
*
* @param string $form_id
*
* @return Form
* @throws \OutOfRangeException
*/
public function get_form($form_id)
{
if ($this->is_form_exists($form_id)) {
return $this->forms[(string) $form_id];
}
throw new \OutOfRangeException('Form with this key not exists');
}
/**
* Get forms data. This method merge all arrays from forms and return associative array for woocommerce form_fields.
*
* @param bool $prefixed if true add form_id as prefix to form keys
*
* @return array
*/
public function get_forms_data($prefixed = \false)
{
$forms_data = array();
foreach ($this->forms as $form) {
if (!$form->is_active()) {
continue;
}
if ($prefixed) {
$forms_data = \array_merge($forms_data, $form->get_prefixed_form_data());
} else {
$forms_data = \array_merge($forms_data, $form->get_form_data());
}
}
return $forms_data;
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace FSVendor\WPDesk\Forms\Persistence;
use Psr\Container\NotFoundExceptionInterface;
use FSVendor\WPDesk\Forms\FieldProvider;
use FSVendor\WPDesk\Persistence\PersistentContainer;
/**
* Can save/load provided fields to/from PersistentContainer.
*
* @package WPDesk\Forms
*/
class FieldPersistenceStrategy
{
/** @var PersistentContainer */
private $persistence;
public function __construct(\FSVendor\WPDesk\Persistence\PersistentContainer $persistence)
{
$this->persistence = $persistence;
}
/**
* Save fields data.
*
* @param FieldProvider $fields_provider
* @param array $data
*/
public function persist_fields(\FSVendor\WPDesk\Forms\FieldProvider $fields_provider, array $data)
{
foreach ($fields_provider->get_fields() as $field) {
$field_key = $field->get_name();
$this->persistence->set($field_key, $field->get_serializer()->serialize($data[$field_key]));
}
}
/**
* Load fields data.
*
* @return array
*/
public function load_fields(\FSVendor\WPDesk\Forms\FieldProvider $fields_provider)
{
$data = [];
foreach ($fields_provider->get_fields() as $field) {
$field_key = $field->get_name();
try {
$data[$field_key] = $field->get_serializer()->unserialize($this->persistence->get($field_key));
} catch (\Psr\Container\NotFoundExceptionInterface $not_found) {
// TODO: Logger
// LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" );
}
}
return $data;
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace FSVendor\WPDesk\Forms\Renderer;
use FSVendor\WPDesk\Forms\FieldProvider;
use FSVendor\WPDesk\Forms\FieldRenderer;
/**
* Can render form fields as JSON.
*
* @package WPDesk\Forms\Renderer
*/
class JsonNormalizedRenderer implements \FSVendor\WPDesk\Forms\FieldRenderer
{
/**
* @param FieldProvider $provider
* @param array $fields_data
* @param string $name_prefix
*
* @return array Normalized fields with data.
*/
public function render_fields(\FSVendor\WPDesk\Forms\FieldProvider $provider, array $fields_data, $name_prefix = '')
{
$rendered_fields = [];
foreach ($provider->get_fields() as $field) {
$rendered = ['name' => $field->get_name(), 'template' => $field->get_template_name(), 'multiple' => $field->is_multiple(), 'disabled' => $field->is_disabled(), 'readonly' => $field->is_readonly(), 'required' => $field->is_required(), 'prefix' => $name_prefix, 'value ' => isset($fields_data[$field->get_name()]) ? $fields_data[$field->get_name()] : $field->get_default_value()];
if ($field->has_classes()) {
$rendered['class'] = $field->get_classes();
}
if ($field->has_description()) {
$rendered['description'] = $field->get_description();
}
if ($field->has_description_tip()) {
$rendered['description_tip'] = $field->get_description_tip();
}
if ($field->has_label()) {
$rendered['label'] = $field->get_label();
}
if ($field->has_placeholder()) {
$rendered['placeholder'] = $field->get_placeholder();
}
$options = $field->get_possible_values();
if ($options) {
$rendered['options'] = $options;
}
if ($field->has_data()) {
$data = $field->get_data();
$rendered['data'] = [];
foreach ($data as $data_name => $data_value) {
$rendered['data'][] = ['name' => $data_name, 'value' => $data_value];
}
}
if (\json_encode($rendered) !== \false) {
$rendered_fields[] = $rendered;
}
}
return $rendered_fields;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace FSVendor\WPDesk\Forms\Resolver;
use FSVendor\WPDesk\View\Renderer\Renderer;
use FSVendor\WPDesk\View\Resolver\DirResolver;
use FSVendor\WPDesk\View\Resolver\Resolver;
/**
* Use with View to resolver form fields to default templates.
*
* @package WPDesk\Forms\Resolver
*/
class DefaultFormFieldResolver implements \FSVendor\WPDesk\View\Resolver\Resolver
{
/** @var Resolver */
private $dir_resolver;
public function __construct()
{
$this->dir_resolver = new \FSVendor\WPDesk\View\Resolver\DirResolver(__DIR__ . '/../../templates');
}
public function resolve($name, \FSVendor\WPDesk\View\Renderer\Renderer $renderer = null)
{
return $this->dir_resolver->resolve($name, $renderer);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace FSVendor\WPDesk\Forms;
interface Sanitizer
{
/**
* @param mixed $value
*
* @return string
*/
public function sanitize($value);
}

View File

@@ -0,0 +1,17 @@
<?php
namespace FSVendor\WPDesk\Forms\Sanitizer;
use FSVendor\WPDesk\Forms\Sanitizer;
class CallableSanitizer implements \FSVendor\WPDesk\Forms\Sanitizer
{
private $callable;
public function __construct($callable)
{
$this->callable = $callable;
}
public function sanitize($value)
{
return \call_user_func($this->callable, $value);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace FSVendor\WPDesk\Forms\Sanitizer;
use FSVendor\WPDesk\Forms\Sanitizer;
class NoSanitize implements \FSVendor\WPDesk\Forms\Sanitizer
{
public function sanitize($value)
{
return $value;
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace FSVendor\WPDesk\Forms\Sanitizer;
use FSVendor\WPDesk\Forms\Sanitizer;
class TextFieldSanitizer implements \FSVendor\WPDesk\Forms\Sanitizer
{
public function sanitize($value)
{
return \sanitize_text_field($value);
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace FSVendor\WPDesk\Forms;
interface Serializer
{
public function serialize($value);
public function unserialize($value);
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms\Serializer;
use FSVendor\WPDesk\Forms\Serializer;
class JsonSerializer implements \FSVendor\WPDesk\Forms\Serializer
{
public function serialize($value)
{
return \json_encode($value);
}
public function unserialize($value)
{
return \json_decode($value, \true);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace FSVendor\WPDesk\Forms\Serializer;
use FSVendor\WPDesk\Forms\Serializer;
class NoSerialize implements \FSVendor\WPDesk\Forms\Serializer
{
public function serialize($value)
{
return $value;
}
public function unserialize($value)
{
return $value;
}
}

Some files were not shown because too many files have changed in this diff Show More