first commit
This commit is contained in:
69
system/library/cache.php
Normal file
69
system/library/cache.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Cache
|
||||
*/
|
||||
class Cache {
|
||||
/**
|
||||
* @var object|mixed
|
||||
*/
|
||||
private object $adaptor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor The type of storage for the cache.
|
||||
* @param int $expire Optional parameters
|
||||
*
|
||||
*/
|
||||
public function __construct(string $adaptor, int $expire = 3600) {
|
||||
$class = 'Opencart\System\Library\Cache\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
$this->adaptor = new $class($expire);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load cache adaptor ' . $adaptor . ' cache!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a cache by key name.
|
||||
*
|
||||
* @param string $key The cache key name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
return $this->adaptor->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* Sets a cache by key value.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
* @param string $value The cache value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0): void {
|
||||
$this->adaptor->set($key, $value, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a cache by key name.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
*/
|
||||
public function delete(string $key): void {
|
||||
$this->adaptor->delete($key);
|
||||
}
|
||||
}
|
94
system/library/cache/apcu.php
vendored
Normal file
94
system/library/cache/apcu.php
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cache;
|
||||
/**
|
||||
* Class APCU
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class APCU {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $expire;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private bool $active;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $expire
|
||||
*/
|
||||
public function __construct(int $expire = 3600) {
|
||||
$this->expire = $expire;
|
||||
$this->active = function_exists('apcu_cache_info') && ini_get('apc.enabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
return $this->active ? apcu_fetch(CACHE_PREFIX . $key) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0): void {
|
||||
if (!$expire) {
|
||||
$expire = $this->expire;
|
||||
}
|
||||
|
||||
if ($this->active) {
|
||||
apcu_store(CACHE_PREFIX . $key, $value, $expire);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $key): void {
|
||||
if ($this->active) {
|
||||
$cache_info = apcu_cache_info();
|
||||
|
||||
$cache_list = $cache_info['cache_list'];
|
||||
|
||||
foreach ($cache_list as $entry) {
|
||||
if (strpos($entry['info'], CACHE_PREFIX . $key) === 0) {
|
||||
apcu_delete($entry['info']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache
|
||||
*
|
||||
* @param null
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush(): bool {
|
||||
$status = false;
|
||||
|
||||
if (function_exists('apcu_clear_cache')) {
|
||||
$status = apcu_clear_cache();
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
95
system/library/cache/file.php
vendored
Normal file
95
system/library/cache/file.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cache;
|
||||
/**
|
||||
* Class File
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class File {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $expire;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $expire
|
||||
*/
|
||||
public function __construct(int $expire = 3600) {
|
||||
$this->expire = $expire;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');
|
||||
|
||||
if ($files) {
|
||||
return json_decode(file_get_contents($files[0]), true);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0): void {
|
||||
$this->delete($key);
|
||||
|
||||
if (!$expire) {
|
||||
$expire = $this->expire;
|
||||
}
|
||||
|
||||
file_put_contents(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.' . (time() + $expire), json_encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $key): void {
|
||||
$files = glob(DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.*');
|
||||
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
if (!@unlink($file)) {
|
||||
clearstatcache(false, $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
public function __destruct() {
|
||||
$files = glob(DIR_CACHE . 'cache.*');
|
||||
|
||||
if ($files && rand(1, 100) == 1) {
|
||||
foreach ($files as $file) {
|
||||
$time = substr(strrchr($file, '.'), 1);
|
||||
|
||||
if ($time < time()) {
|
||||
if (!@unlink($file)) {
|
||||
clearstatcache(false, $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
system/library/cache/mem.php
vendored
Normal file
69
system/library/cache/mem.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cache;
|
||||
/**
|
||||
* Class Mem
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Mem {
|
||||
/**
|
||||
* @var object|\Memcache
|
||||
*/
|
||||
private object $memcache;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $expire;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const CACHEDUMP_LIMIT = 9999;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $expire
|
||||
*/
|
||||
public function __construct(int $expire = 3600) {
|
||||
$this->expire = $expire;
|
||||
|
||||
$this->memcache = new \Memcache();
|
||||
$this->memcache->pconnect(CACHE_HOSTNAME, CACHE_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
return $this->memcache->get(CACHE_PREFIX . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $value
|
||||
* @param int $expire
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0) {
|
||||
if (!$expire) {
|
||||
$expire = $this->expire;
|
||||
}
|
||||
|
||||
$this->memcache->set(CACHE_PREFIX . $key, $value, MEMCACHE_COMPRESSED, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function delete(string $key) {
|
||||
$this->memcache->delete(CACHE_PREFIX . $key);
|
||||
}
|
||||
}
|
69
system/library/cache/memcached.php
vendored
Normal file
69
system/library/cache/memcached.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cache;
|
||||
/**
|
||||
* Class Memcached
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Memcached {
|
||||
/**
|
||||
* @var object|\Memcached
|
||||
*/
|
||||
private object $memcached;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $expire;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const CACHEDUMP_LIMIT = 9999;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $expire
|
||||
*/
|
||||
public function __construct(int $expire = 3600) {
|
||||
$this->expire = $expire;
|
||||
|
||||
$this->memcached = new \Memcached();
|
||||
$this->memcached->addServer(CACHE_HOSTNAME, CACHE_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
return $this->memcached->get(CACHE_PREFIX . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $value
|
||||
* @param int $expire
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0) {
|
||||
if (!$expire) {
|
||||
$expire = $this->expire;
|
||||
}
|
||||
|
||||
$this->memcached->set(CACHE_PREFIX . $key, $value, $expire);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function delete(string $key) {
|
||||
$this->memcached->delete(CACHE_PREFIX . $key);
|
||||
}
|
||||
}
|
70
system/library/cache/redis.php
vendored
Normal file
70
system/library/cache/redis.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cache;
|
||||
/**
|
||||
* Class Redis
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Redis {
|
||||
/**
|
||||
* @var object|\Redis
|
||||
*/
|
||||
private object $redis;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $expire;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $expire
|
||||
*/
|
||||
public function __construct(int $expire = 3600) {
|
||||
$this->expire = $expire;
|
||||
|
||||
$this->redis = new \Redis();
|
||||
$this->redis->pconnect(CACHE_HOSTNAME, CACHE_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function get(string $key): array|string|null {
|
||||
$data = $this->redis->get(CACHE_PREFIX . $key);
|
||||
|
||||
return json_decode($data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $value
|
||||
* @param int $expire
|
||||
*/
|
||||
public function set(string $key, array|string|null $value, int $expire = 0) {
|
||||
if (!$expire) {
|
||||
$expire = $this->expire;
|
||||
}
|
||||
|
||||
$status = $this->redis->set(CACHE_PREFIX . $key, json_encode($value));
|
||||
|
||||
if ($status) {
|
||||
$this->redis->expire(CACHE_PREFIX . $key, $expire);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function delete(string $key): void {
|
||||
$this->redis->del(CACHE_PREFIX . $key);
|
||||
}
|
||||
}
|
600
system/library/cart/cart.php
Normal file
600
system/library/cart/cart.php
Normal file
@ -0,0 +1,600 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Cart
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Cart {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $config;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $customer;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $session;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $tax;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $weight;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $data = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
$this->customer = $registry->get('customer');
|
||||
$this->session = $registry->get('session');
|
||||
$this->tax = $registry->get('tax');
|
||||
$this->weight = $registry->get('weight');
|
||||
|
||||
// Remove all the expired carts with no customer ID
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "cart` WHERE (`api_id` > '0' OR `customer_id` = '0') AND `date_added` < DATE_SUB(NOW(), INTERVAL 1 HOUR)");
|
||||
|
||||
if ($this->customer->isLogged()) {
|
||||
// We want to change the session ID on all the old items in the customers cart
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "cart` SET `session_id` = '" . $this->db->escape($this->session->getId()) . "' WHERE `api_id` = '0' AND `customer_id` = '" . (int)$this->customer->getId() . "'");
|
||||
|
||||
// Once the customer is logged in we want to update the customers cart
|
||||
$cart_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "cart` WHERE `api_id` = '0' AND `customer_id` = '0' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "'");
|
||||
|
||||
foreach ($cart_query->rows as $cart) {
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "cart` WHERE `cart_id` = '" . (int)$cart['cart_id'] . "'");
|
||||
|
||||
// The advantage of using $this->add is that it will check if the products already exist and increase the quantity if necessary.
|
||||
$this->add($cart['product_id'], $cart['quantity'], json_decode($cart['option'], true), $cart['subscription_plan_id'], $cart['override'], $cart['price']);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the cart data
|
||||
$this->data = $this->getProducts();
|
||||
}
|
||||
|
||||
/**
|
||||
* getProducts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProducts(): array {
|
||||
if (!$this->data) {
|
||||
$cart_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "cart` WHERE `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "'");
|
||||
|
||||
foreach ($cart_query->rows as $cart) {
|
||||
$stock = true;
|
||||
|
||||
$product_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_store` `p2s` LEFT JOIN `" . DB_PREFIX . "product` p ON (p2s.`product_id` = p.`product_id`) LEFT JOIN `" . DB_PREFIX . "product_description` pd ON (p.`product_id` = pd.`product_id`) WHERE p2s.`store_id` = '" . (int)$this->config->get('config_store_id') . "' AND p2s.`product_id` = '" . (int)$cart['product_id'] . "' AND pd.`language_id` = '" . (int)$this->config->get('config_language_id') . "' AND p.`date_available` <= NOW() AND p.`status` = '1'");
|
||||
|
||||
if ($product_query->num_rows && ($cart['quantity'] > 0)) {
|
||||
$option_price = 0;
|
||||
$option_points = 0;
|
||||
$option_weight = 0;
|
||||
|
||||
$option_data = [];
|
||||
|
||||
$product_options = (array)json_decode($cart['option'], true);
|
||||
|
||||
// Merge variant code with options
|
||||
$variant = json_decode($product_query->row['variant'], true);
|
||||
|
||||
if ($variant) {
|
||||
foreach ($variant as $key => $value) {
|
||||
$product_options[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($product_options as $product_option_id => $value) {
|
||||
if (!$product_query->row['master_id']) {
|
||||
$product_id = $cart['product_id'];
|
||||
} else {
|
||||
$product_id = $product_query->row['master_id'];
|
||||
}
|
||||
|
||||
$option_query = $this->db->query("SELECT po.`product_option_id`, po.`option_id`, od.`name`, o.`type` FROM `" . DB_PREFIX . "product_option` po LEFT JOIN `" . DB_PREFIX . "option` o ON (po.`option_id` = o.`option_id`) LEFT JOIN `" . DB_PREFIX . "option_description` od ON (o.`option_id` = od.`option_id`) WHERE po.`product_option_id` = '" . (int)$product_option_id . "' AND po.`product_id` = '" . (int)$product_id . "' AND od.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
if ($option_query->num_rows) {
|
||||
if ($option_query->row['type'] == 'select' || $option_query->row['type'] == 'radio') {
|
||||
$option_value_query = $this->db->query("SELECT pov.`option_value_id`, ovd.`name`, pov.`quantity`, pov.`subtract`, pov.`price`, pov.`price_prefix`, pov.`points`, pov.`points_prefix`, pov.`weight`, pov.`weight_prefix` FROM `" . DB_PREFIX . "product_option_value` pov LEFT JOIN `" . DB_PREFIX . "option_value` ov ON (pov.`option_value_id` = ov.`option_value_id`) LEFT JOIN `" . DB_PREFIX . "option_value_description` ovd ON (ov.`option_value_id` = ovd.`option_value_id`) WHERE pov.`product_option_value_id` = '" . (int)$value . "' AND pov.`product_option_id` = '" . (int)$product_option_id . "' AND ovd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
if ($option_value_query->num_rows) {
|
||||
if ($option_value_query->row['price_prefix'] == '+') {
|
||||
$option_price += $option_value_query->row['price'];
|
||||
} elseif ($option_value_query->row['price_prefix'] == '-') {
|
||||
$option_price -= $option_value_query->row['price'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['points_prefix'] == '+') {
|
||||
$option_points += $option_value_query->row['points'];
|
||||
} elseif ($option_value_query->row['points_prefix'] == '-') {
|
||||
$option_points -= $option_value_query->row['points'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['weight_prefix'] == '+') {
|
||||
$option_weight += $option_value_query->row['weight'];
|
||||
} elseif ($option_value_query->row['weight_prefix'] == '-') {
|
||||
$option_weight -= $option_value_query->row['weight'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['subtract'] && (!$option_value_query->row['quantity'] || ($option_value_query->row['quantity'] < $cart['quantity']))) {
|
||||
$stock = false;
|
||||
}
|
||||
|
||||
$option_data[] = [
|
||||
'product_option_id' => $product_option_id,
|
||||
'product_option_value_id' => $value,
|
||||
'option_id' => $option_query->row['option_id'],
|
||||
'option_value_id' => $option_value_query->row['option_value_id'],
|
||||
'name' => $option_query->row['name'],
|
||||
'value' => $option_value_query->row['name'],
|
||||
'type' => $option_query->row['type'],
|
||||
'quantity' => $option_value_query->row['quantity'],
|
||||
'subtract' => $option_value_query->row['subtract'],
|
||||
'price' => $option_value_query->row['price'],
|
||||
'price_prefix' => $option_value_query->row['price_prefix'],
|
||||
'points' => $option_value_query->row['points'],
|
||||
'points_prefix' => $option_value_query->row['points_prefix'],
|
||||
'weight' => $option_value_query->row['weight'],
|
||||
'weight_prefix' => $option_value_query->row['weight_prefix']
|
||||
];
|
||||
}
|
||||
} elseif ($option_query->row['type'] == 'checkbox' && is_array($value)) {
|
||||
foreach ($value as $product_option_value_id) {
|
||||
$option_value_query = $this->db->query("SELECT pov.`option_value_id`, pov.`quantity`, pov.`subtract`, pov.`price`, pov.`price_prefix`, pov.`points`, pov.`points_prefix`, pov.`weight`, pov.`weight_prefix`, ovd.`name` FROM `" . DB_PREFIX . "product_option_value` `pov` LEFT JOIN `" . DB_PREFIX . "option_value_description` ovd ON (pov.`option_value_id` = ovd.option_value_id) WHERE pov.product_option_value_id = '" . (int)$product_option_value_id . "' AND pov.product_option_id = '" . (int)$product_option_id . "' AND ovd.language_id = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
if ($option_value_query->num_rows) {
|
||||
if ($option_value_query->row['price_prefix'] == '+') {
|
||||
$option_price += $option_value_query->row['price'];
|
||||
} elseif ($option_value_query->row['price_prefix'] == '-') {
|
||||
$option_price -= $option_value_query->row['price'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['points_prefix'] == '+') {
|
||||
$option_points += $option_value_query->row['points'];
|
||||
} elseif ($option_value_query->row['points_prefix'] == '-') {
|
||||
$option_points -= $option_value_query->row['points'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['weight_prefix'] == '+') {
|
||||
$option_weight += $option_value_query->row['weight'];
|
||||
} elseif ($option_value_query->row['weight_prefix'] == '-') {
|
||||
$option_weight -= $option_value_query->row['weight'];
|
||||
}
|
||||
|
||||
if ($option_value_query->row['subtract'] && (!$option_value_query->row['quantity'] || ($option_value_query->row['quantity'] < $cart['quantity']))) {
|
||||
$stock = false;
|
||||
}
|
||||
|
||||
$option_data[] = ['product_option_id' => $product_option_id,
|
||||
'product_option_value_id' => $product_option_value_id,
|
||||
'option_id' => $option_query->row['option_id'],
|
||||
'option_value_id' => $option_value_query->row['option_value_id'],
|
||||
'name' => $option_query->row['name'],
|
||||
'value' => $option_value_query->row['name'],
|
||||
'type' => $option_query->row['type'],
|
||||
'quantity' => $option_value_query->row['quantity'],
|
||||
'subtract' => $option_value_query->row['subtract'],
|
||||
'price' => $option_value_query->row['price'],
|
||||
'price_prefix' => $option_value_query->row['price_prefix'],
|
||||
'points' => $option_value_query->row['points'],
|
||||
'points_prefix' => $option_value_query->row['points_prefix'],
|
||||
'weight' => $option_value_query->row['weight'],
|
||||
'weight_prefix' => $option_value_query->row['weight_prefix']
|
||||
];
|
||||
}
|
||||
}
|
||||
} elseif ($option_query->row['type'] == 'text' || $option_query->row['type'] == 'textarea' || $option_query->row['type'] == 'file' || $option_query->row['type'] == 'date' || $option_query->row['type'] == 'datetime' || $option_query->row['type'] == 'time') {
|
||||
$option_data[] = ['product_option_id' => $product_option_id,
|
||||
'product_option_value_id' => '',
|
||||
'option_id' => $option_query->row['option_id'],
|
||||
'option_value_id' => '',
|
||||
'name' => $option_query->row['name'],
|
||||
'value' => $value,
|
||||
'type' => $option_query->row['type'],
|
||||
'quantity' => '',
|
||||
'subtract' => '',
|
||||
'price' => '',
|
||||
'price_prefix' => '',
|
||||
'points' => '',
|
||||
'points_prefix' => '',
|
||||
'weight' => '',
|
||||
'weight_prefix' => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$price = $product_query->row['price'];
|
||||
|
||||
// Product Discounts
|
||||
$discount_quantity = 0;
|
||||
|
||||
foreach ($cart_query->rows as $cart_2) {
|
||||
if ($cart_2['product_id'] == $cart['product_id']) {
|
||||
$discount_quantity += $cart_2['quantity'];
|
||||
}
|
||||
}
|
||||
|
||||
$product_discount_query = $this->db->query("SELECT `price` FROM `" . DB_PREFIX . "product_discount` WHERE `product_id` = '" . (int)$cart['product_id'] . "' AND `customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND `quantity` <= '" . (int)$discount_quantity . "' AND ((`date_start` = '0000-00-00' OR `date_start` < NOW()) AND (`date_end` = '0000-00-00' OR `date_end` > NOW())) ORDER BY `quantity` DESC, `priority` ASC, `price` ASC LIMIT 1");
|
||||
|
||||
if ($product_discount_query->num_rows) {
|
||||
$price = $product_discount_query->row['price'];
|
||||
}
|
||||
|
||||
// Product Specials
|
||||
$product_special_query = $this->db->query("SELECT `price` FROM `" . DB_PREFIX . "product_special` WHERE `product_id` = '" . (int)$cart['product_id'] . "' AND `customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND ((`date_start` = '0000-00-00' OR `date_start` < NOW()) AND (`date_end` = '0000-00-00' OR `date_end` > NOW())) ORDER BY `priority` ASC, `price` ASC LIMIT 1");
|
||||
|
||||
if ($product_special_query->num_rows) {
|
||||
$price = $product_special_query->row['price'];
|
||||
}
|
||||
|
||||
$product_total = 0;
|
||||
|
||||
foreach ($cart_query->rows as $cart_2) {
|
||||
if ($cart_2['product_id'] == $cart['product_id']) {
|
||||
$product_total += $cart_2['quantity'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($product_query->row['minimum'] > $product_total) {
|
||||
$minimum = false;
|
||||
} else {
|
||||
$minimum = true;
|
||||
}
|
||||
|
||||
// Reward Points
|
||||
$product_reward_query = $this->db->query("SELECT `points` FROM `" . DB_PREFIX . "product_reward` WHERE `product_id` = '" . (int)$cart['product_id'] . "' AND `customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "'");
|
||||
|
||||
if ($product_reward_query->num_rows) {
|
||||
$reward = $product_reward_query->row['points'];
|
||||
} else {
|
||||
$reward = 0;
|
||||
}
|
||||
|
||||
// Downloads
|
||||
$download_data = [];
|
||||
|
||||
$download_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_to_download` p2d LEFT JOIN `" . DB_PREFIX . "download` d ON (p2d.`download_id` = d.`download_id`) LEFT JOIN `" . DB_PREFIX . "download_description` dd ON (d.`download_id` = dd.`download_id`) WHERE p2d.`product_id` = '" . (int)$cart['product_id'] . "' AND dd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
foreach ($download_query->rows as $download) {
|
||||
$download_data[] = [
|
||||
'download_id' => $download['download_id'],
|
||||
'name' => $download['name'],
|
||||
'filename' => $download['filename'],
|
||||
'mask' => $download['mask']
|
||||
];
|
||||
}
|
||||
|
||||
// Stock
|
||||
if (!$product_query->row['quantity'] || ($product_query->row['quantity'] < $cart['quantity'])) {
|
||||
$stock = false;
|
||||
}
|
||||
|
||||
$subscription_data = [];
|
||||
|
||||
$subscription_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product_subscription` ps LEFT JOIN `" . DB_PREFIX . "subscription_plan` sp ON (ps.`subscription_plan_id` = sp.`subscription_plan_id`) LEFT JOIN `" . DB_PREFIX . "subscription_plan_description` spd ON (sp.`subscription_plan_id` = spd.`subscription_plan_id`) WHERE ps.`product_id` = '" . (int)$cart['product_id'] . "' AND ps.`subscription_plan_id` = '" . (int)$cart['subscription_plan_id'] . "' AND ps.`customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND spd.`language_id` = '" . (int)$this->config->get('config_language_id') . "' AND sp.`status` = '1'");
|
||||
|
||||
if ($subscription_query->num_rows) {
|
||||
$price = $subscription_query->row['price'];
|
||||
|
||||
if ($subscription_query->row['trial_status']) {
|
||||
$price = $subscription_query->row['trial_price'];
|
||||
}
|
||||
|
||||
$subscription_data = [
|
||||
'subscription_plan_id' => $subscription_query->row['subscription_plan_id'],
|
||||
'name' => $subscription_query->row['name'],
|
||||
'trial_price' => $subscription_query->row['trial_price'],
|
||||
'trial_frequency' => $subscription_query->row['trial_frequency'],
|
||||
'trial_cycle' => $subscription_query->row['trial_cycle'],
|
||||
'trial_duration' => $subscription_query->row['trial_duration'],
|
||||
'trial_remaining' => $subscription_query->row['trial_duration'],
|
||||
'trial_status' => $subscription_query->row['trial_status'],
|
||||
'price' => $subscription_query->row['price'],
|
||||
'frequency' => $subscription_query->row['frequency'],
|
||||
'cycle' => $subscription_query->row['cycle'],
|
||||
'duration' => $subscription_query->row['duration'],
|
||||
'remaining' => $subscription_query->row['duration']
|
||||
];
|
||||
}
|
||||
|
||||
if ($cart['override']) {
|
||||
$price = $cart['price'];
|
||||
}
|
||||
|
||||
$this->data[$cart['cart_id']] = [
|
||||
'cart_id' => $cart['cart_id'],
|
||||
'product_id' => $product_query->row['product_id'],
|
||||
'master_id' => $product_query->row['master_id'],
|
||||
'name' => $product_query->row['name'],
|
||||
'model' => $product_query->row['model'],
|
||||
'shipping' => $product_query->row['shipping'],
|
||||
'image' => $product_query->row['image'],
|
||||
'option' => $option_data,
|
||||
'subscription' => $subscription_data,
|
||||
'download' => $download_data,
|
||||
'quantity' => $cart['quantity'],
|
||||
'minimum' => $minimum,
|
||||
'subtract' => $product_query->row['subtract'],
|
||||
'stock' => $stock,
|
||||
'price' => ($price + $option_price),
|
||||
'total' => ($price + $option_price) * $cart['quantity'],
|
||||
'reward' => $reward * $cart['quantity'],
|
||||
'points' => ($product_query->row['points'] ? ($product_query->row['points'] + $option_points) * $cart['quantity'] : 0),
|
||||
'tax_class_id' => $product_query->row['tax_class_id'],
|
||||
'weight' => ($product_query->row['weight'] + $option_weight) * $cart['quantity'],
|
||||
'weight_class_id' => $product_query->row['weight_class_id'],
|
||||
'length' => $product_query->row['length'],
|
||||
'width' => $product_query->row['width'],
|
||||
'height' => $product_query->row['height'],
|
||||
'length_class_id' => $product_query->row['length_class_id']
|
||||
];
|
||||
} else {
|
||||
$this->remove($cart['cart_id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add
|
||||
*
|
||||
* @param int $product_id
|
||||
* @param int $quantity
|
||||
* @param array $option
|
||||
* @param int $subscription_plan_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add(int $product_id, int $quantity = 1, array $option = [], int $subscription_plan_id = 0, bool $override = false, float $price = 0): void {
|
||||
$query = $this->db->query("SELECT COUNT(*) AS `total` FROM `" . DB_PREFIX . "cart` WHERE `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "' AND `product_id` = '" . (int)$product_id . "' AND `subscription_plan_id` = '" . (int)$subscription_plan_id . "' AND `option` = '" . $this->db->escape(json_encode($option)) . "'");
|
||||
|
||||
if (!$query->row['total']) {
|
||||
$this->db->query("INSERT INTO `" . DB_PREFIX . "cart` SET `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "', `customer_id` = '" . (int)$this->customer->getId() . "', `session_id` = '" . $this->db->escape($this->session->getId()) . "', `product_id` = '" . (int)$product_id . "', `subscription_plan_id` = '" . (int)$subscription_plan_id . "', `option` = '" . $this->db->escape(json_encode($option)) . "', `quantity` = '" . (int)$quantity . "', `override` = '" . (bool)$override . "', `price` = '" . (float)($override ? $price : 0) . "', `date_added` = NOW()");
|
||||
} else {
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "cart` SET `quantity` = (`quantity` + " . (int)$quantity . ") WHERE `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "' AND `product_id` = '" . (int)$product_id . "' AND `subscription_plan_id` = '" . (int)$subscription_plan_id . "' AND `option` = '" . $this->db->escape(json_encode($option)) . "'");
|
||||
}
|
||||
|
||||
// Populate the cart data
|
||||
$this->data = $this->getProducts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
* @param int $cart_id
|
||||
* @param int $quantity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update(int $cart_id, int $quantity): void {
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "cart` SET `quantity` = '" . (int)$quantity . "' WHERE `cart_id` = '" . (int)$cart_id . "' AND `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "'");
|
||||
|
||||
// Populate the cart data
|
||||
$this->data = $this->getProducts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Has
|
||||
*
|
||||
* @param int $cart_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(int $cart_id): bool {
|
||||
return isset($this->data[$cart_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove
|
||||
*
|
||||
* @param int $cart_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove(int $cart_id): void {
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "cart` WHERE `cart_id` = '" . (int)$cart_id . "' AND `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "'");
|
||||
|
||||
unset($this->data[$cart_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear(): void {
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "cart` WHERE `api_id` = '" . (isset($this->session->data['api_id']) ? (int)$this->session->data['api_id'] : 0) . "' AND `customer_id` = '" . (int)$this->customer->getId() . "' AND `session_id` = '" . $this->db->escape($this->session->getId()) . "'");
|
||||
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* getSubscription
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSubscriptions(): array {
|
||||
$product_data = [];
|
||||
|
||||
foreach ($this->getProducts() as $value) {
|
||||
if ($value['subscription']) {
|
||||
$product_data[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $product_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* getWeight
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getWeight(): float {
|
||||
$weight = 0;
|
||||
|
||||
foreach ($this->getProducts() as $product) {
|
||||
if ($product['shipping']) {
|
||||
$weight += $this->weight->convert($product['weight'], $product['weight_class_id'], $this->config->get('config_weight_class_id'));
|
||||
}
|
||||
}
|
||||
|
||||
return $weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* getSubTotal
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getSubTotal(): float {
|
||||
$total = 0;
|
||||
|
||||
foreach ($this->getProducts() as $product) {
|
||||
$total += $product['total'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTaxes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTaxes(): array {
|
||||
$tax_data = [];
|
||||
|
||||
foreach ($this->getProducts() as $product) {
|
||||
if ($product['tax_class_id']) {
|
||||
$tax_rates = $this->tax->getRates($product['price'], $product['tax_class_id']);
|
||||
|
||||
foreach ($tax_rates as $tax_rate) {
|
||||
if (!isset($tax_data[$tax_rate['tax_rate_id']])) {
|
||||
$tax_data[$tax_rate['tax_rate_id']] = ($tax_rate['amount'] * $product['quantity']);
|
||||
} else {
|
||||
$tax_data[$tax_rate['tax_rate_id']] += ($tax_rate['amount'] * $product['quantity']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tax_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTotal
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getTotal(): float {
|
||||
$total = 0;
|
||||
|
||||
foreach ($this->getProducts() as $product) {
|
||||
$total += $this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')) * $product['quantity'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* countProducts
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countProducts(): int {
|
||||
$product_total = 0;
|
||||
|
||||
$products = $this->getProducts();
|
||||
|
||||
foreach ($products as $product) {
|
||||
$product_total += $product['quantity'];
|
||||
}
|
||||
|
||||
return $product_total;
|
||||
}
|
||||
|
||||
/**
|
||||
* hadProducts
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasProducts(): bool {
|
||||
return (bool)count($this->getProducts());
|
||||
}
|
||||
|
||||
/**
|
||||
* hasSubscription
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSubscription(): bool {
|
||||
return (bool)count($this->getSubscriptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* hasStock
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStock(): bool {
|
||||
foreach ($this->getProducts() as $product) {
|
||||
if (!$product['stock']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hasShipping
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasShipping(): bool {
|
||||
foreach ($this->getProducts() as $product) {
|
||||
if ($product['shipping']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* hasDownload
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDownload(): bool {
|
||||
foreach ($this->getProducts() as $product) {
|
||||
if ($product['download']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
195
system/library/cart/currency.php
Normal file
195
system/library/cart/currency.php
Normal file
@ -0,0 +1,195 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Currency
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Currency {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $language;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $currencies = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->language = $registry->get('language');
|
||||
|
||||
$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "currency`");
|
||||
|
||||
foreach ($query->rows as $result) {
|
||||
$this->currencies[$result['code']] = ['currency_id' => $result['currency_id'], 'title' => $result['title'], 'symbol_left' => $result['symbol_left'], 'symbol_right' => $result['symbol_right'], 'decimal_place' => $result['decimal_place'], 'value' => $result['value']];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format
|
||||
*
|
||||
* @param float $number
|
||||
* @param string $currency
|
||||
* @param float $value
|
||||
* @param bool $format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function format(float $number, string $currency, float $value = 0, bool $format = true): string {
|
||||
if (!isset($this->currencies[$currency])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$symbol_left = $this->currencies[$currency]['symbol_left'];
|
||||
$symbol_right = $this->currencies[$currency]['symbol_right'];
|
||||
$decimal_place = $this->currencies[$currency]['decimal_place'];
|
||||
|
||||
if (!$value) {
|
||||
$value = $this->currencies[$currency]['value'];
|
||||
}
|
||||
|
||||
$amount = $value ? (float)$number * $value : (float)$number;
|
||||
|
||||
$amount = round($amount, $decimal_place);
|
||||
|
||||
if (!$format) {
|
||||
return $amount;
|
||||
}
|
||||
|
||||
$string = '';
|
||||
|
||||
if ($symbol_left) {
|
||||
$string .= $symbol_left;
|
||||
}
|
||||
|
||||
$string .= number_format($amount, $decimal_place, $this->language->get('decimal_point'), $this->language->get('thousand_point'));
|
||||
|
||||
if ($symbol_right) {
|
||||
$string .= $symbol_right;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert
|
||||
*
|
||||
* @param float $value
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function convert(float $value, string $from, string $to): float {
|
||||
if (isset($this->currencies[$from])) {
|
||||
$from = $this->currencies[$from]['value'];
|
||||
} else {
|
||||
$from = 1;
|
||||
}
|
||||
|
||||
if (isset($this->currencies[$to])) {
|
||||
$to = $this->currencies[$to]['value'];
|
||||
} else {
|
||||
$to = 1;
|
||||
}
|
||||
|
||||
return $value * ($to / $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* getId
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId(string $currency): int {
|
||||
if (isset($this->currencies[$currency])) {
|
||||
return $this->currencies[$currency]['currency_id'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getSymbolLeft
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymbolLeft(string $currency): string {
|
||||
if (isset($this->currencies[$currency])) {
|
||||
return $this->currencies[$currency]['symbol_left'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getSymbolRight
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSymbolRight(string $currency): string {
|
||||
if (isset($this->currencies[$currency])) {
|
||||
return $this->currencies[$currency]['symbol_right'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getDecimalPlace
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDecimalPlace(string $currency): string {
|
||||
if (isset($this->currencies[$currency])) {
|
||||
return $this->currencies[$currency]['decimal_place'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getValue
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
|
||||
public function getValue(string $currency): float {
|
||||
if (isset($this->currencies[$currency])) {
|
||||
return $this->currencies[$currency]['value'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has
|
||||
*
|
||||
* @param string $currency
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(string $currency): bool {
|
||||
return isset($this->currencies[$currency]);
|
||||
}
|
||||
}
|
256
system/library/cart/customer.php
Normal file
256
system/library/cart/customer.php
Normal file
@ -0,0 +1,256 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Customer
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Customer {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $config;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $request;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $session;
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $customer_id = 0;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $firstname = '';
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $lastname = '';
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $customer_group_id = 0;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $email = '';
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $telephone = '';
|
||||
/**
|
||||
* @var bool|mixed
|
||||
*/
|
||||
private bool $newsletter = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
$this->request = $registry->get('request');
|
||||
$this->session = $registry->get('session');
|
||||
|
||||
if (isset($this->session->data['customer_id'])) {
|
||||
$customer_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer` WHERE `customer_id` = '" . (int)$this->session->data['customer_id'] . "' AND `status` = '1'");
|
||||
|
||||
if ($customer_query->num_rows) {
|
||||
$this->customer_id = $customer_query->row['customer_id'];
|
||||
$this->firstname = $customer_query->row['firstname'];
|
||||
$this->lastname = $customer_query->row['lastname'];
|
||||
$this->customer_group_id = $customer_query->row['customer_group_id'];
|
||||
$this->email = $customer_query->row['email'];
|
||||
$this->telephone = $customer_query->row['telephone'];
|
||||
$this->newsletter = $customer_query->row['newsletter'];
|
||||
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `language_id` = '" . (int)$this->config->get('config_language_id') . "', `ip` = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "' WHERE `customer_id` = '" . (int)$this->customer_id . "'");
|
||||
} else {
|
||||
$this->logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Login
|
||||
*
|
||||
* @param string $email
|
||||
* @param string $password
|
||||
* @param bool $override
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function login(string $email, string $password, bool $override = false): bool {
|
||||
$customer_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "customer` WHERE LCASE(`email`) = '" . $this->db->escape(oc_strtolower($email)) . "' AND `status` = '1'");
|
||||
|
||||
if ($customer_query->row) {
|
||||
if (!$override) {
|
||||
if (password_verify($password, $customer_query->row['password'])) {
|
||||
$rehash = password_needs_rehash($customer_query->row['password'], PASSWORD_DEFAULT);
|
||||
} elseif (isset($customer_query->row['salt']) && $customer_query->row['password'] == sha1($customer_query->row['salt'] . sha1($customer_query->row['salt'] . sha1($password)))) {
|
||||
$rehash = true;
|
||||
} elseif ($customer_query->row['password'] == md5($password)) {
|
||||
$rehash = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($rehash) {
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `password` = '" . $this->db->escape(password_hash($password, PASSWORD_DEFAULT)) . "' WHERE `customer_id` = '" . (int)$customer_query->row['customer_id'] . "'");
|
||||
}
|
||||
}
|
||||
|
||||
$this->session->data['customer_id'] = $customer_query->row['customer_id'];
|
||||
|
||||
$this->customer_id = $customer_query->row['customer_id'];
|
||||
$this->firstname = $customer_query->row['firstname'];
|
||||
$this->lastname = $customer_query->row['lastname'];
|
||||
$this->customer_group_id = $customer_query->row['customer_group_id'];
|
||||
$this->email = $customer_query->row['email'];
|
||||
$this->telephone = $customer_query->row['telephone'];
|
||||
$this->newsletter = $customer_query->row['newsletter'];
|
||||
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "customer` SET `language_id` = '" . (int)$this->config->get('config_language_id') . "', `ip` = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "' WHERE `customer_id` = '" . (int)$this->customer_id . "'");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function logout(): void {
|
||||
unset($this->session->data['customer_id']);
|
||||
|
||||
$this->customer_id = 0;
|
||||
$this->firstname = '';
|
||||
$this->lastname = '';
|
||||
$this->customer_group_id = 0;
|
||||
$this->email = '';
|
||||
$this->telephone = '';
|
||||
$this->newsletter = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* isLogged
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLogged(): bool {
|
||||
return $this->customer_id ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int {
|
||||
return $this->customer_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getFirstName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstName(): string {
|
||||
return $this->firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLastName(): string {
|
||||
return $this->lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* getGroupId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getGroupId(): int {
|
||||
return $this->customer_group_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getEmail
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmail(): string {
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTelephone
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTelephone(): string {
|
||||
return $this->telephone;
|
||||
}
|
||||
|
||||
/**
|
||||
* getNewsletter
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getNewsletter(): bool {
|
||||
return $this->newsletter;
|
||||
}
|
||||
|
||||
/**
|
||||
* getAddressId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAddressId(): int {
|
||||
$query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "address` WHERE `customer_id` = '" . (int)$this->customer_id . "' AND `default` = '1'");
|
||||
|
||||
if ($query->num_rows) {
|
||||
return (int)$query->row['address_id'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getBalance
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getBalance(): float {
|
||||
$query = $this->db->query("SELECT SUM(`amount`) AS `total` FROM `" . DB_PREFIX . "customer_transaction` WHERE `customer_id` = '" . (int)$this->customer_id . "'");
|
||||
|
||||
return (float)$query->row['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* getRewardPoints
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getRewardPoints(): float {
|
||||
$query = $this->db->query("SELECT SUM(`points`) AS `total` FROM `" . DB_PREFIX . "customer_reward` WHERE `customer_id` = '" . (int)$this->customer_id . "'");
|
||||
|
||||
return (float)$query->row['total'];
|
||||
}
|
||||
}
|
104
system/library/cart/length.php
Normal file
104
system/library/cart/length.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Length
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Length {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $config;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $lengths = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
|
||||
$length_class_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "length_class` mc LEFT JOIN `" . DB_PREFIX . "length_class_description` mcd ON (mc.`length_class_id` = mcd.`length_class_id`) WHERE mcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
foreach ($length_class_query->rows as $result) {
|
||||
$this->lengths[$result['length_class_id']] = [
|
||||
'length_class_id' => $result['length_class_id'],
|
||||
'title' => $result['title'],
|
||||
'unit' => $result['unit'],
|
||||
'value' => $result['value']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert
|
||||
*
|
||||
* @param float $value
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function convert(float $value, string $from, string $to): float {
|
||||
if ($from == $to) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (isset($this->lengths[$from])) {
|
||||
$from = $this->lengths[$from]['value'];
|
||||
} else {
|
||||
$from = 1;
|
||||
}
|
||||
|
||||
if (isset($this->lengths[$to])) {
|
||||
$to = $this->lengths[$to]['value'];
|
||||
} else {
|
||||
$to = 1;
|
||||
}
|
||||
|
||||
return $value * ($to / $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $length_class_id
|
||||
* @param string $decimal_point
|
||||
* @param string $thousand_point
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function format(float $value, int $length_class_id, string $decimal_point = '.', string $thousand_point = ','): string {
|
||||
if (isset($this->lengths[$length_class_id])) {
|
||||
return number_format($value, 2, $decimal_point, $thousand_point) . $this->lengths[$length_class_id]['unit'];
|
||||
} else {
|
||||
return number_format($value, 2, $decimal_point, $thousand_point);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getUnit
|
||||
*
|
||||
* @param int $length_class_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnit(int $length_class_id): string {
|
||||
if (isset($this->lengths[$length_class_id])) {
|
||||
return $this->lengths[$length_class_id]['unit'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
210
system/library/cart/tax.php
Normal file
210
system/library/cart/tax.php
Normal file
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Tax
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Tax {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $config;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $tax_rates = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* setShippingAddress
|
||||
*
|
||||
* @param int $country_id
|
||||
* @param int $zone_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setShippingAddress(int $country_id, int $zone_id): void {
|
||||
$tax_query = $this->db->query("SELECT tr1.`tax_class_id`, tr2.`tax_rate_id`, tr2.`name`, tr2.`rate`, tr2.`type`, tr1.`priority` FROM `" . DB_PREFIX . "tax_rule` tr1 LEFT JOIN `" . DB_PREFIX . "tax_rate` tr2 ON (tr1.`tax_rate_id` = tr2.`tax_rate_id`) INNER JOIN `" . DB_PREFIX . "tax_rate_to_customer_group` tr2cg ON (tr2.`tax_rate_id` = tr2cg.`tax_rate_id`) LEFT JOIN `" . DB_PREFIX . "zone_to_geo_zone` z2gz ON (tr2.`geo_zone_id` = z2gz.`geo_zone_id`) LEFT JOIN `" . DB_PREFIX . "geo_zone` gz ON (tr2.`geo_zone_id` = gz.`geo_zone_id`) WHERE tr1.`based` = 'shipping' AND tr2cg.`customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND z2gz.`country_id` = '" . (int)$country_id . "' AND (z2gz.`zone_id` = '0' OR z2gz.`zone_id` = '" . (int)$zone_id . "') ORDER BY tr1.`priority` ASC");
|
||||
|
||||
foreach ($tax_query->rows as $result) {
|
||||
$this->tax_rates[$result['tax_class_id']][$result['tax_rate_id']] = [
|
||||
'tax_rate_id' => $result['tax_rate_id'],
|
||||
'name' => $result['name'],
|
||||
'rate' => $result['rate'],
|
||||
'type' => $result['type'],
|
||||
'priority' => $result['priority']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setPaymentAddress
|
||||
*
|
||||
* @param int $country_id
|
||||
* @param int $zone_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setPaymentAddress(int $country_id, int $zone_id): void {
|
||||
$tax_query = $this->db->query("SELECT tr1.`tax_class_id`, tr2.`tax_rate_id`, tr2.`name`, tr2.`rate`, tr2.`type`, tr1.`priority` FROM `" . DB_PREFIX . "tax_rule` tr1 LEFT JOIN `" . DB_PREFIX . "tax_rate` tr2 ON (tr1.`tax_rate_id` = tr2.`tax_rate_id`) INNER JOIN `" . DB_PREFIX . "tax_rate_to_customer_group` tr2cg ON (tr2.`tax_rate_id` = tr2cg.`tax_rate_id`) LEFT JOIN `" . DB_PREFIX . "zone_to_geo_zone` z2gz ON (tr2.`geo_zone_id` = z2gz.`geo_zone_id`) LEFT JOIN `" . DB_PREFIX . "geo_zone` gz ON (tr2.`geo_zone_id` = gz.`geo_zone_id`) WHERE tr1.`based` = 'payment' AND tr2cg.`customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND z2gz.`country_id` = '" . (int)$country_id . "' AND (z2gz.`zone_id` = '0' OR z2gz.`zone_id` = '" . (int)$zone_id . "') ORDER BY tr1.`priority` ASC");
|
||||
|
||||
foreach ($tax_query->rows as $result) {
|
||||
$this->tax_rates[$result['tax_class_id']][$result['tax_rate_id']] = [
|
||||
'tax_rate_id' => $result['tax_rate_id'],
|
||||
'name' => $result['name'],
|
||||
'rate' => $result['rate'],
|
||||
'type' => $result['type'],
|
||||
'priority' => $result['priority']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setStoreAddress
|
||||
*
|
||||
* @param int $country_id
|
||||
* @param int $zone_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setStoreAddress(int $country_id, int $zone_id): void {
|
||||
$tax_query = $this->db->query("SELECT tr1.`tax_class_id`, tr2.`tax_rate_id`, tr2.`name`, tr2.`rate`, tr2.`type`, tr1.`priority` FROM `" . DB_PREFIX . "tax_rule` tr1 LEFT JOIN `" . DB_PREFIX . "tax_rate` tr2 ON (tr1.`tax_rate_id` = tr2.`tax_rate_id`) INNER JOIN `" . DB_PREFIX . "tax_rate_to_customer_group` tr2cg ON (tr2.`tax_rate_id` = tr2cg.`tax_rate_id`) LEFT JOIN `" . DB_PREFIX . "zone_to_geo_zone` z2gz ON (tr2.`geo_zone_id` = z2gz.`geo_zone_id`) LEFT JOIN `" . DB_PREFIX . "geo_zone` gz ON (tr2.`geo_zone_id` = gz.`geo_zone_id`) WHERE tr1.`based` = 'store' AND tr2cg.`customer_group_id` = '" . (int)$this->config->get('config_customer_group_id') . "' AND z2gz.`country_id` = '" . (int)$country_id . "' AND (z2gz.`zone_id` = '0' OR z2gz.`zone_id` = '" . (int)$zone_id . "') ORDER BY tr1.`priority` ASC");
|
||||
|
||||
foreach ($tax_query->rows as $result) {
|
||||
$this->tax_rates[$result['tax_class_id']][$result['tax_rate_id']] = [
|
||||
'tax_rate_id' => $result['tax_rate_id'],
|
||||
'name' => $result['name'],
|
||||
'rate' => $result['rate'],
|
||||
'type' => $result['type'],
|
||||
'priority' => $result['priority']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $tax_class_id
|
||||
* @param bool $calculate
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function calculate(float $value, int $tax_class_id, bool $calculate = true): float {
|
||||
if ($tax_class_id && $calculate) {
|
||||
$amount = 0;
|
||||
|
||||
$tax_rates = $this->getRates($value, $tax_class_id);
|
||||
|
||||
foreach ($tax_rates as $tax_rate) {
|
||||
if ($calculate != 'P' && $calculate != 'F') {
|
||||
$amount += $tax_rate['amount'];
|
||||
} elseif ($tax_rate['type'] == $calculate) {
|
||||
$amount += $tax_rate['amount'];
|
||||
}
|
||||
}
|
||||
|
||||
return $value + $amount;
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getTax
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $tax_class_id
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getTax(float $value, int $tax_class_id): float {
|
||||
$amount = 0;
|
||||
|
||||
$tax_rates = $this->getRates($value, $tax_class_id);
|
||||
|
||||
foreach ($tax_rates as $tax_rate) {
|
||||
$amount += $tax_rate['amount'];
|
||||
}
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* getRateName
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRateName(int $tax_rate_id): string {
|
||||
$tax_query = $this->db->query("SELECT `name` FROM `" . DB_PREFIX . "tax_rate` WHERE `tax_rate_id` = '" . (int)$tax_rate_id . "'");
|
||||
|
||||
if ($tax_query->num_rows) {
|
||||
return $tax_query->row['name'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getRates
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $tax_class_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRates(float $value, int $tax_class_id): array {
|
||||
$tax_rate_data = [];
|
||||
|
||||
if (isset($this->tax_rates[$tax_class_id])) {
|
||||
foreach ($this->tax_rates[$tax_class_id] as $tax_rate) {
|
||||
if (isset($tax_rate_data[$tax_rate['tax_rate_id']])) {
|
||||
$amount = $tax_rate_data[$tax_rate['tax_rate_id']]['amount'];
|
||||
} else {
|
||||
$amount = 0;
|
||||
}
|
||||
|
||||
if ($tax_rate['type'] == 'F') {
|
||||
$amount += $tax_rate['rate'];
|
||||
} elseif ($tax_rate['type'] == 'P') {
|
||||
$amount += ($value / 100 * $tax_rate['rate']);
|
||||
}
|
||||
|
||||
$tax_rate_data[$tax_rate['tax_rate_id']] = [
|
||||
'tax_rate_id' => $tax_rate['tax_rate_id'],
|
||||
'name' => $tax_rate['name'],
|
||||
'rate' => $tax_rate['rate'],
|
||||
'type' => $tax_rate['type'],
|
||||
'amount' => $amount
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $tax_rate_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear(): void {
|
||||
$this->tax_rates = [];
|
||||
}
|
||||
}
|
201
system/library/cart/user.php
Normal file
201
system/library/cart/user.php
Normal file
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class User
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class User {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $request;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $session;
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $user_id = 0;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $username = '';
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $user_group_id = 0;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $email = '';
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $permission = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->request = $registry->get('request');
|
||||
$this->session = $registry->get('session');
|
||||
|
||||
if (isset($this->session->data['user_id'])) {
|
||||
$user_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user` WHERE `user_id` = '" . (int)$this->session->data['user_id'] . "' AND `status` = '1'");
|
||||
|
||||
if ($user_query->num_rows) {
|
||||
$this->user_id = $user_query->row['user_id'];
|
||||
$this->username = $user_query->row['username'];
|
||||
$this->user_group_id = $user_query->row['user_group_id'];
|
||||
$this->email = $user_query->row['email'];
|
||||
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "user` SET `ip` = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "' WHERE `user_id` = '" . (int)$this->session->data['user_id'] . "'");
|
||||
|
||||
$user_group_query = $this->db->query("SELECT `permission` FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_query->row['user_group_id'] . "'");
|
||||
|
||||
$permissions = json_decode($user_group_query->row['permission'], true);
|
||||
|
||||
if (is_array($permissions)) {
|
||||
foreach ($permissions as $key => $value) {
|
||||
$this->permission[$key] = $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Login
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function login(string $username, string $password): bool {
|
||||
$user_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "user` WHERE `username` = '" . $this->db->escape($username) . "' AND `status` = '1'");
|
||||
|
||||
if ($user_query->num_rows) {
|
||||
if (password_verify($password, $user_query->row['password'])) {
|
||||
$rehash = password_needs_rehash($user_query->row['password'], PASSWORD_DEFAULT);
|
||||
} elseif (isset($user_query->row['salt']) && $user_query->row['password'] == sha1($user_query->row['salt'] . sha1($user_query->row['salt'] . sha1($password)))) {
|
||||
$rehash = true;
|
||||
} elseif ($user_query->row['password'] == md5($password)) {
|
||||
$rehash = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($rehash) {
|
||||
$this->db->query("UPDATE `" . DB_PREFIX . "user` SET `password` = '" . $this->db->escape(password_hash($password, PASSWORD_DEFAULT)) . "' WHERE `user_id` = '" . (int)$user_query->row['user_id'] . "'");
|
||||
}
|
||||
|
||||
$this->session->data['user_id'] = $user_query->row['user_id'];
|
||||
|
||||
$this->user_id = $user_query->row['user_id'];
|
||||
$this->username = $user_query->row['username'];
|
||||
$this->user_group_id = $user_query->row['user_group_id'];
|
||||
$this->email = $user_query->row['email'];
|
||||
|
||||
$user_group_query = $this->db->query("SELECT `permission` FROM `" . DB_PREFIX . "user_group` WHERE `user_group_id` = '" . (int)$user_query->row['user_group_id'] . "'");
|
||||
|
||||
$permissions = json_decode($user_group_query->row['permission'], true);
|
||||
|
||||
if (is_array($permissions)) {
|
||||
foreach ($permissions as $key => $value) {
|
||||
$this->permission[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function logout(): void {
|
||||
unset($this->session->data['user_id']);
|
||||
|
||||
$this->user_id = 0;
|
||||
$this->username = '';
|
||||
$this->user_group_id = 0;
|
||||
$this->email = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* hasPermission
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPermission(string $key, mixed $value): bool {
|
||||
if (isset($this->permission[$key])) {
|
||||
return in_array($value, $this->permission[$key]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isLogged
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLogged(): bool {
|
||||
return $this->user_id ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int {
|
||||
return $this->user_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getUserName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUserName(): string {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* getGroupId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getGroupId(): int {
|
||||
return $this->user_group_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getEmail
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmail(): string {
|
||||
return $this->email;
|
||||
}
|
||||
}
|
104
system/library/cart/weight.php
Normal file
104
system/library/cart/weight.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Cart;
|
||||
/**
|
||||
* Class Weight
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Weight {
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $db;
|
||||
/**
|
||||
* @var object|mixed|null
|
||||
*/
|
||||
private object $config;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $weights = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
|
||||
$weight_class_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "weight_class` wc LEFT JOIN `" . DB_PREFIX . "weight_class_description` wcd ON (wc.`weight_class_id` = wcd.`weight_class_id`) WHERE wcd.`language_id` = '" . (int)$this->config->get('config_language_id') . "'");
|
||||
|
||||
foreach ($weight_class_query->rows as $result) {
|
||||
$this->weights[$result['weight_class_id']] = [
|
||||
'weight_class_id' => $result['weight_class_id'],
|
||||
'title' => $result['title'],
|
||||
'unit' => $result['unit'],
|
||||
'value' => $result['value']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert
|
||||
*
|
||||
* @param float $value
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function convert(float $value, string $from, string $to): float {
|
||||
if ($from == $to) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (isset($this->weights[$from])) {
|
||||
$from = $this->weights[$from]['value'];
|
||||
} else {
|
||||
$from = 1;
|
||||
}
|
||||
|
||||
if (isset($this->weights[$to])) {
|
||||
$to = $this->weights[$to]['value'];
|
||||
} else {
|
||||
$to = 1;
|
||||
}
|
||||
|
||||
return $value * ($to / $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format
|
||||
*
|
||||
* @param float $value
|
||||
* @param string $weight_class_id
|
||||
* @param string $decimal_point
|
||||
* @param string $thousand_point
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function format(float $value, string $weight_class_id, string $decimal_point = '.', string $thousand_point = ','): string {
|
||||
if (isset($this->weights[$weight_class_id])) {
|
||||
return number_format($value, 2, $decimal_point, $thousand_point) . $this->weights[$weight_class_id]['unit'];
|
||||
} else {
|
||||
return number_format($value, 2, $decimal_point, $thousand_point);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getUnit
|
||||
*
|
||||
* @param int $weight_class_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUnit(int $weight_class_id): string {
|
||||
if (isset($this->weights[$weight_class_id])) {
|
||||
return $this->weights[$weight_class_id]['unit'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
94
system/library/db.php
Normal file
94
system/library/db.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class DB Adapter
|
||||
*/
|
||||
class DB {
|
||||
/**
|
||||
* @var object|mixed
|
||||
*/
|
||||
private object $adaptor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $database
|
||||
* @param int $port
|
||||
*
|
||||
*/
|
||||
public function __construct(string $adaptor, string $hostname, string $username, string $password, string $database, string $port = '') {
|
||||
$class = 'Opencart\System\Library\DB\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
$this->adaptor = new $class($hostname, $username, $password, $database, $port);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load database adaptor ' . $adaptor . '!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $sql SQL statement to be executed
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function query(string $sql): bool|object {
|
||||
return $this->adaptor->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape
|
||||
*
|
||||
* @param string $value Value to be protected against SQL injections
|
||||
*
|
||||
* @return string returns escaped value
|
||||
*/
|
||||
public function escape(string $value): string {
|
||||
return $this->adaptor->escape($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count Affected
|
||||
*
|
||||
* Gets the total number of affected rows from the last query
|
||||
*
|
||||
* @return int returns the total number of affected rows.
|
||||
*/
|
||||
public function countAffected(): int {
|
||||
return $this->adaptor->countAffected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Last ID
|
||||
*
|
||||
* Get the last ID gets the primary key that was returned after creating a row in a table.
|
||||
*
|
||||
* @return int returns last ID
|
||||
*/
|
||||
public function getLastId(): int {
|
||||
return $this->adaptor->getLastId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Connected
|
||||
*
|
||||
* Checks if a DB connection is active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected(): bool {
|
||||
return $this->adaptor->isConnected();
|
||||
}
|
||||
}
|
131
system/library/db/mysqli.php
Normal file
131
system/library/db/mysqli.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\DB;
|
||||
/**
|
||||
* Class MySQLi
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class MySQLi {
|
||||
/**
|
||||
* @var object|\mysqli|null
|
||||
*/
|
||||
private object|null $connection;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $database
|
||||
* @param string $port
|
||||
*/
|
||||
public function __construct(string $hostname, string $username, string $password, string $database, string $port = '') {
|
||||
if (!$port) {
|
||||
$port = '3306';
|
||||
}
|
||||
|
||||
try {
|
||||
$mysqli = @new \MySQLi($hostname, $username, $password, $database, $port);
|
||||
|
||||
$this->connection = $mysqli;
|
||||
$this->connection->set_charset('utf8mb4');
|
||||
|
||||
$this->query("SET SESSION sql_mode = 'NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION'");
|
||||
$this->query("SET FOREIGN_KEY_CHECKS = 0");
|
||||
|
||||
// Sync PHP and DB time zones
|
||||
$this->query("SET `time_zone` = '" . $this->escape(date('P')) . "'");
|
||||
} catch (\mysqli_sql_exception $e) {
|
||||
throw new \Exception('Error: Could not make a database link using ' . $username . '@' . $hostname . '!<br/>Message: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $sql
|
||||
*
|
||||
* @return bool|object
|
||||
*/
|
||||
public function query(string $sql): bool|object {
|
||||
try {
|
||||
$query = $this->connection->query($sql);
|
||||
|
||||
if ($query instanceof \mysqli_result) {
|
||||
$data = [];
|
||||
|
||||
while ($row = $query->fetch_assoc()) {
|
||||
$data[] = $row;
|
||||
}
|
||||
|
||||
$result = new \stdClass();
|
||||
$result->num_rows = $query->num_rows;
|
||||
$result->row = isset($data[0]) ? $data[0] : [];
|
||||
$result->rows = $data;
|
||||
|
||||
$query->close();
|
||||
|
||||
unset($data);
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (\mysqli_sql_exception $e) {
|
||||
throw new \Exception('Error: ' . $this->connection->error . '<br/>Error No: ' . $this->connection->errno . '<br/>' . $sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape
|
||||
*
|
||||
* @param string value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape(string $value): string {
|
||||
return $this->connection->real_escape_string($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* countAffected
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAffected(): int {
|
||||
return $this->connection->affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastId(): int {
|
||||
return $this->connection->insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* isConnected
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected(): bool {
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* Closes the DB connection when this object is destroyed.
|
||||
*
|
||||
*/
|
||||
public function __destruct() {
|
||||
if ($this->connection) {
|
||||
$this->connection->close();
|
||||
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
||||
}
|
147
system/library/db/pdo.php
Normal file
147
system/library/db/pdo.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\DB;
|
||||
/**
|
||||
* Class PDO
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class PDO {
|
||||
/**
|
||||
* @var object|\PDO|null
|
||||
*/
|
||||
private object|null $connection;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $data = [];
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $affected;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $database
|
||||
* @param string $port
|
||||
*/
|
||||
public function __construct(string $hostname, string $username, string $password, string $database, string $port = '') {
|
||||
if (!$port) {
|
||||
$port = '3306';
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = @new \PDO('mysql:host=' . $hostname . ';port=' . $port . ';dbname=' . $database . ';charset=utf8mb4', $username, $password, array(\PDO::ATTR_PERSISTENT => false, \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_general_ci'));
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Exception('Error: Could not make a database link using ' . $username . '@' . $hostname . '!');
|
||||
}
|
||||
|
||||
if ($pdo) {
|
||||
$this->connection = $pdo;
|
||||
|
||||
$this->query("SET SESSION sql_mode = 'NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION'");
|
||||
$this->query("SET FOREIGN_KEY_CHECKS = 0");
|
||||
|
||||
// Sync PHP and DB time zones
|
||||
$this->query("SET `time_zone` = '" . $this->escape(date('P')) . "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $sql
|
||||
*
|
||||
* @return bool|object
|
||||
*/
|
||||
public function query(string $sql): bool|object {
|
||||
$sql = preg_replace('/(?:\'\:)([a-z0-9]*.)(?:\')/', ':$1', $sql);
|
||||
|
||||
$statement = $this->connection->prepare($sql);
|
||||
|
||||
try {
|
||||
if ($statement && $statement->execute($this->data)) {
|
||||
$this->data = [];
|
||||
|
||||
if ($statement->columnCount()) {
|
||||
$data = $statement->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
$result = new \stdClass();
|
||||
$result->row = isset($data[0]) ? $data[0] : [];
|
||||
$result->rows = $data;
|
||||
$result->num_rows = count($data);
|
||||
$this->affected = 0;
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
$this->affected = $statement->rowCount();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$statement->closeCursor();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
throw new \Exception('Error: ' . $e->getMessage() . ' <br/>Error Code : ' . $e->getCode() . ' <br/>' . $sql);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape
|
||||
*
|
||||
* @param string value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape(string $value): string {
|
||||
$key = ':' . count($this->data);
|
||||
|
||||
$this->data[$key] = $value;
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* countAffected
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAffected(): int {
|
||||
return $this->affected;
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastId(): int {
|
||||
return $this->connection->lastInsertId();
|
||||
}
|
||||
|
||||
/**
|
||||
* isConnected
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected(): bool {
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* Closes the DB connection when this object is destroyed.
|
||||
*
|
||||
*/
|
||||
public function __destruct() {
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
136
system/library/db/pgsql.php
Normal file
136
system/library/db/pgsql.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\DB;
|
||||
/**
|
||||
* Class PgSQL
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class PgSQL {
|
||||
/**
|
||||
* @var object|resource|null
|
||||
*/
|
||||
private object|null $connection;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $hostname
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string $database
|
||||
* @param string $port
|
||||
*/
|
||||
public function __construct(string $hostname, string $username, string $password, string $database, string $port = '') {
|
||||
if (!$port) {
|
||||
$port = '5432';
|
||||
}
|
||||
|
||||
try {
|
||||
$pg = @pg_connect('host=' . $hostname . ' port=' . $port . ' user=' . $username . ' password=' . $password . ' dbname=' . $database . ' options=\'--client_encoding=UTF8\' ');
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Error: Could not make a database link using ' . $username . '@' . $hostname);
|
||||
}
|
||||
|
||||
if ($pg) {
|
||||
$this->connection = $pg;
|
||||
pg_query($this->connection, "SET CLIENT_ENCODING TO 'UTF8'");
|
||||
|
||||
// Sync PHP and DB time zones
|
||||
pg_query($this->connection, "SET TIMEZONE = '" . $this->escape(date('P')) . "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $sql
|
||||
*
|
||||
* @return bool|object
|
||||
*/
|
||||
public function query(string $sql): bool|object {
|
||||
$resource = pg_query($this->connection, $sql);
|
||||
|
||||
if ($resource) {
|
||||
if (is_resource($resource)) {
|
||||
$i = 0;
|
||||
|
||||
$data = [];
|
||||
|
||||
while ($result = pg_fetch_assoc($resource)) {
|
||||
$data[$i] = $result;
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
pg_free_result($resource);
|
||||
|
||||
$query = new \stdClass();
|
||||
$query->row = isset($data[0]) ? $data[0] : [];
|
||||
$query->rows = $data;
|
||||
$query->num_rows = $i;
|
||||
|
||||
unset($data);
|
||||
|
||||
return $query;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Error: ' . pg_result_error($resource) . '<br/>' . $sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape
|
||||
*
|
||||
* @param string value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function escape(string $value): string {
|
||||
return pg_escape_string($this->connection, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* countAffected
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAffected(): int {
|
||||
return pg_affected_rows($this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* getLastId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastId(): int {
|
||||
$query = $this->query("SELECT LASTVAL() AS `id`");
|
||||
|
||||
return $query->row['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* isConnected
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected(): bool {
|
||||
return pg_connection_status($this->connection) == PGSQL_CONNECTION_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* Closes the DB connection when this object is destroyed.
|
||||
*
|
||||
*/
|
||||
public function __destruct() {
|
||||
if ($this->connection) {
|
||||
pg_close($this->connection);
|
||||
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
||||
}
|
165
system/library/document.php
Normal file
165
system/library/document.php
Normal file
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2017, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Document
|
||||
*/
|
||||
class Document {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $title = '';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $description = '';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $keywords = '';
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $links = [];
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $styles = [];
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $scripts = [];
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle(string $title): void {
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* getTitle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): string {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $description
|
||||
*/
|
||||
public function setDescription(string $description): void {
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription(): string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $keywords
|
||||
*/
|
||||
public function setKeywords(string $keywords): void {
|
||||
$this->keywords = $keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeywords(): string {
|
||||
return $this->keywords;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $href
|
||||
* @param string $rel
|
||||
*/
|
||||
public function addLink(string $href, string $rel): void {
|
||||
$this->links[$href] = [
|
||||
'href' => $href,
|
||||
'rel' => $rel
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLinks(): array {
|
||||
return $this->links;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $href
|
||||
* @param string $rel
|
||||
* @param string $media
|
||||
*/
|
||||
public function addStyle(string $href, $rel = 'stylesheet', $media = 'screen'): void {
|
||||
$this->styles[$href] = [
|
||||
'href' => $href,
|
||||
'rel' => $rel,
|
||||
'media' => $media
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getStyles(): array {
|
||||
return $this->styles;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $href
|
||||
* @param string $position
|
||||
*/
|
||||
public function addScript(string $href, $position = 'header'): void {
|
||||
$this->scripts[$position][$href] = ['href' => $href];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param string $position
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getScripts($position = 'header'): array {
|
||||
if (isset($this->scripts[$position])) {
|
||||
return $this->scripts[$position];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
62
system/library/encryption.php
Normal file
62
system/library/encryption.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr, Billy Noah
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Encryption
|
||||
*/
|
||||
class Encryption {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $cipher = 'aes-256-ctr';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $digest = 'sha256';
|
||||
|
||||
/**
|
||||
* Encrypt
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encrypt(string $key, string $value): string {
|
||||
$key = openssl_digest($key, $this->digest, true);
|
||||
$iv_length = openssl_cipher_iv_length($this->cipher);
|
||||
$iv = openssl_random_pseudo_bytes($iv_length);
|
||||
|
||||
return base64_encode($iv . openssl_encrypt($value, $this->cipher, $key, OPENSSL_RAW_DATA, $iv));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt(string $key, string $value): string {
|
||||
$result = '';
|
||||
|
||||
$key = openssl_digest($key, $this->digest, true);
|
||||
$iv_length = openssl_cipher_iv_length($this->cipher);
|
||||
$value = base64_decode($value);
|
||||
$iv = substr($value, 0, $iv_length);
|
||||
$value = substr($value, $iv_length);
|
||||
|
||||
if (strlen($iv) == $iv_length) {
|
||||
$result = openssl_decrypt($value, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
388
system/library/image.php
Normal file
388
system/library/image.php
Normal file
@ -0,0 +1,388 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Image
|
||||
*/
|
||||
class Image {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $file;
|
||||
/**
|
||||
* @var object|false|\GdImage|resource
|
||||
*/
|
||||
private object $image;
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $width;
|
||||
/**
|
||||
* @var int|mixed
|
||||
*/
|
||||
private int $height;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $bits;
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private string $mime;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
*/
|
||||
public function __construct(string $file) {
|
||||
if (!extension_loaded('gd')) {
|
||||
exit('Error: PHP GD is not installed!');
|
||||
}
|
||||
|
||||
if (is_file($file)) {
|
||||
$this->file = $file;
|
||||
|
||||
$info = getimagesize($file);
|
||||
|
||||
$this->width = $info[0];
|
||||
$this->height = $info[1];
|
||||
$this->bits = isset($info['bits']) ? $info['bits'] : '';
|
||||
$this->mime = isset($info['mime']) ? $info['mime'] : '';
|
||||
|
||||
if ($this->mime == 'image/gif') {
|
||||
$this->image = imagecreatefromgif($file);
|
||||
} elseif ($this->mime == 'image/png') {
|
||||
$this->image = imagecreatefrompng($file);
|
||||
|
||||
imageinterlace($this->image, false);
|
||||
} elseif ($this->mime == 'image/jpeg') {
|
||||
$this->image = imagecreatefromjpeg($file);
|
||||
} elseif ($this->mime == 'image/webp') {
|
||||
$this->image = imagecreatefromwebp($file);
|
||||
}
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load image ' . $file . '!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getFile
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFile(): string {
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* getImage
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getImage(): object {
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* getWidth
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth(): int {
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* getHeight
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight(): int {
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* getBits
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBits(): string {
|
||||
return $this->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* getMime
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMime(): string {
|
||||
return $this->mime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $quality
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save(string $file, int $quality = 90): void {
|
||||
$info = pathinfo($file);
|
||||
|
||||
$extension = strtolower($info['extension']);
|
||||
|
||||
if (is_object($this->image) || is_resource($this->image)) {
|
||||
if ($extension == 'jpeg' || $extension == 'jpg') {
|
||||
imagejpeg($this->image, $file, $quality);
|
||||
} elseif ($extension == 'png') {
|
||||
imagepng($this->image, $file);
|
||||
} elseif ($extension == 'gif') {
|
||||
imagegif($this->image, $file);
|
||||
} elseif ($extension == 'webp') {
|
||||
imagewebp($this->image, $file);
|
||||
}
|
||||
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $default
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resize(int $width = 0, int $height = 0, string $default = ''): void {
|
||||
if (!$this->width || !$this->height) {
|
||||
return;
|
||||
}
|
||||
|
||||
$xpos = 0;
|
||||
$ypos = 0;
|
||||
$scale = 1;
|
||||
|
||||
$scale_w = $width / $this->width;
|
||||
$scale_h = $height / $this->height;
|
||||
|
||||
if ($default == 'w') {
|
||||
$scale = $scale_w;
|
||||
} elseif ($default == 'h') {
|
||||
$scale = $scale_h;
|
||||
} else {
|
||||
$scale = min($scale_w, $scale_h);
|
||||
}
|
||||
|
||||
if ($scale == 1 && $scale_h == $scale_w && ($this->mime != 'image/png' || $this->mime != 'image/webp')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$new_width = (int)($this->width * $scale);
|
||||
$new_height = (int)($this->height * $scale);
|
||||
$xpos = (int)(($width - $new_width) / 2);
|
||||
$ypos = (int)(($height - $new_height) / 2);
|
||||
|
||||
$image_old = $this->image;
|
||||
$this->image = imagecreatetruecolor($width, $height);
|
||||
|
||||
if ($this->mime == 'image/png') {
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
|
||||
$background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
|
||||
|
||||
imagecolortransparent($this->image, $background);
|
||||
|
||||
} elseif ($this->mime == 'image/webp') {
|
||||
imagealphablending($this->image, false);
|
||||
imagesavealpha($this->image, true);
|
||||
|
||||
$background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
|
||||
|
||||
imagecolortransparent($this->image, $background);
|
||||
} else {
|
||||
$background = imagecolorallocate($this->image, 255, 255, 255);
|
||||
}
|
||||
|
||||
imagefilledrectangle($this->image, 0, 0, $width, $height, $background);
|
||||
|
||||
imagecopyresampled($this->image, $image_old, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->width, $this->height);
|
||||
imagedestroy($image_old);
|
||||
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Watermark
|
||||
*
|
||||
* @param object $watermark
|
||||
* @param string $position
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function watermark(\Opencart\System\Library\Image $watermark, string $position = 'bottomright'): void {
|
||||
switch ($position) {
|
||||
case 'topleft':
|
||||
$watermark_pos_x = 0;
|
||||
$watermark_pos_y = 0;
|
||||
break;
|
||||
case 'topcenter':
|
||||
$watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
|
||||
$watermark_pos_y = 0;
|
||||
break;
|
||||
case 'topright':
|
||||
$watermark_pos_x = ($this->width - $watermark->getWidth());
|
||||
$watermark_pos_y = 0;
|
||||
break;
|
||||
case 'middleleft':
|
||||
$watermark_pos_x = 0;
|
||||
$watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
|
||||
break;
|
||||
case 'middlecenter':
|
||||
$watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
|
||||
$watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
|
||||
break;
|
||||
case 'middleright':
|
||||
$watermark_pos_x = ($this->width - $watermark->getWidth());
|
||||
$watermark_pos_y = (int)(($this->height - $watermark->getHeight()) / 2);
|
||||
break;
|
||||
case 'bottomleft':
|
||||
$watermark_pos_x = 0;
|
||||
$watermark_pos_y = ($this->height - $watermark->getHeight());
|
||||
break;
|
||||
case 'bottomcenter':
|
||||
$watermark_pos_x = (int)(($this->width - $watermark->getWidth()) / 2);
|
||||
$watermark_pos_y = ($this->height - $watermark->getHeight());
|
||||
break;
|
||||
case 'bottomright':
|
||||
$watermark_pos_x = ($this->width - $watermark->getWidth());
|
||||
$watermark_pos_y = ($this->height - $watermark->getHeight());
|
||||
break;
|
||||
}
|
||||
|
||||
imagealphablending($this->image, true);
|
||||
imagesavealpha($this->image, true);
|
||||
imagecopy($this->image, $watermark->getImage(), $watermark_pos_x, $watermark_pos_y, 0, 0, $watermark->getWidth(), $watermark->getHeight());
|
||||
|
||||
imagedestroy($watermark->getImage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Crop
|
||||
*
|
||||
* @param int $top_x
|
||||
* @param int $top_y
|
||||
* @param int $bottom_x
|
||||
* @param int $bottom_y
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function crop(int $top_x, int $top_y, int $bottom_x, int $bottom_y): void {
|
||||
$image_old = $this->image;
|
||||
$this->image = imagecreatetruecolor($bottom_x - $top_x, $bottom_y - $top_y);
|
||||
|
||||
imagecopy($this->image, $image_old, 0, 0, $top_x, $top_y, $this->width, $this->height);
|
||||
imagedestroy($image_old);
|
||||
|
||||
$this->width = $bottom_x - $top_x;
|
||||
$this->height = $bottom_y - $top_y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate
|
||||
*
|
||||
* @param int $degree
|
||||
* @param string $color
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rotate(int $degree, string $color = 'FFFFFF'): void {
|
||||
$rgb = $this->html2rgb($color);
|
||||
|
||||
$this->image = imagerotate($this->image, $degree, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));
|
||||
|
||||
$this->width = imagesx($this->image);
|
||||
$this->height = imagesy($this->image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function filter(): void {
|
||||
$args = func_get_args();
|
||||
|
||||
call_user_func_array('imagefilter', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Text
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $size
|
||||
* @param string $color
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function text(string $text, int $x = 0, int $y = 0, int $size = 5, string $color = '000000'): void {
|
||||
$rgb = $this->html2rgb($color);
|
||||
|
||||
imagestring($this->image, $size, $x, $y, $text, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge
|
||||
*
|
||||
* @param object $merge
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param int $opacity
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function merge(object $merge, int $x = 0, int $y = 0, int $opacity = 100): void {
|
||||
imagecopymerge($this->image, $merge->getImage(), $x, $y, 0, 0, $merge->getWidth(), $merge->getHeight(), $opacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML2RGB
|
||||
*
|
||||
* @param string $color
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function html2rgb(string $color): array {
|
||||
if ($color[0] == '#') {
|
||||
$color = substr($color, 1);
|
||||
}
|
||||
|
||||
if (strlen($color) == 6) {
|
||||
[$r, $g, $b] = [$color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5]];
|
||||
} elseif (strlen($color) == 3) {
|
||||
[$r, $g, $b] = [$color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
$r = hexdec($r);
|
||||
$g = hexdec($g);
|
||||
$b = hexdec($b);
|
||||
|
||||
return [$r, $g, $b];
|
||||
}
|
||||
}
|
170
system/library/language.php
Normal file
170
system/library/language.php
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Language
|
||||
*/
|
||||
class Language {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $code;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $directory;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $path = [];
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $data = [];
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $cache = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $code
|
||||
*
|
||||
*/
|
||||
public function __construct(string $code) {
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* addPath
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $directory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPath(string $namespace, string $directory = ''): void {
|
||||
if (!$directory) {
|
||||
$this->directory = $namespace;
|
||||
} else {
|
||||
$this->path[$namespace] = $directory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get language text string
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get(string $key) {
|
||||
return isset($this->data[$key]) ? $this->data[$key] : $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set language text string
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function set(string $key, string $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* All
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(string $prefix = ''): array {
|
||||
if (!$prefix) {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$_ = [];
|
||||
|
||||
$length = strlen($prefix);
|
||||
|
||||
foreach ($this->data as $key => $value) {
|
||||
if (substr($key, 0, $length) == $prefix) {
|
||||
$_[substr($key, $length + 1)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear(): void {
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $code Language code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function load(string $filename, string $prefix = '', string $code = ''): array {
|
||||
if (!$code) {
|
||||
$code = $this->code;
|
||||
}
|
||||
|
||||
if (!isset($this->cache[$code][$filename])) {
|
||||
$_ = [];
|
||||
|
||||
// Load selected language file to overwrite the default language keys
|
||||
$file = $this->directory . $code . '/' . $filename . '.php';
|
||||
|
||||
$namespace = '';
|
||||
|
||||
$parts = explode('/', $filename);
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (!$namespace) {
|
||||
$namespace .= $part;
|
||||
} else {
|
||||
$namespace .= '/' . $part;
|
||||
}
|
||||
|
||||
if (isset($this->path[$namespace])) {
|
||||
$file = $this->path[$namespace] . $code . substr($filename, strlen($namespace)) . '.php';
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($file)) {
|
||||
require($file);
|
||||
}
|
||||
|
||||
$this->cache[$code][$filename] = $_;
|
||||
} else {
|
||||
$_ = $this->cache[$code][$filename];
|
||||
}
|
||||
|
||||
if ($prefix) {
|
||||
foreach ($_ as $key => $value) {
|
||||
$_[$prefix . '_' . $key] = $value;
|
||||
|
||||
unset($_[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->data = array_merge($this->data, $_);
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
}
|
38
system/library/log.php
Normal file
38
system/library/log.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Log
|
||||
*/
|
||||
class Log {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $file;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
public function __construct(string $filename) {
|
||||
$this->file = DIR_LOGS . $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function write(string|array $message): void {
|
||||
file_put_contents($this->file, date('Y-m-d H:i:s') . ' - ' . print_r($message, true) . "\n", FILE_APPEND);
|
||||
}
|
||||
}
|
152
system/library/mail.php
Normal file
152
system/library/mail.php
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2017, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Mail
|
||||
*/
|
||||
class Mail {
|
||||
private object $adaptor;
|
||||
private array $option = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
* @param array $option
|
||||
*
|
||||
*/
|
||||
public function __construct(string $adaptor = 'mail', array $option = []) {
|
||||
$class = 'Opencart\System\Library\Mail\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
$this->option = &$option;
|
||||
|
||||
$this->adaptor = new $class($option);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load mail adaptor ' . $adaptor . '!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setTo
|
||||
*
|
||||
* @param string $to
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setTo(string|array $to): void {
|
||||
$this->option['to'] = $to;
|
||||
}
|
||||
|
||||
/**
|
||||
* setFrom
|
||||
*
|
||||
* @param string $from
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setFrom(string $from): void {
|
||||
$this->option['from'] = $from;
|
||||
}
|
||||
|
||||
/**
|
||||
* setSender
|
||||
*
|
||||
* @param string $sender
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSender(string $sender): void {
|
||||
$this->option['sender'] = $sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* setReplyTo
|
||||
*
|
||||
* @param string $reply_to
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setReplyTo(string $reply_to): void {
|
||||
$this->option['reply_to'] = $reply_to;
|
||||
}
|
||||
|
||||
/**
|
||||
* setSubject
|
||||
*
|
||||
* @param string $subject
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSubject(string $subject): void {
|
||||
$this->option['subject'] = $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* setText
|
||||
*
|
||||
* @param string $text
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setText(string $text): void {
|
||||
$this->option['text'] = $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* setHtml
|
||||
*
|
||||
* @param string $html
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setHtml(string $html): void {
|
||||
$this->option['html'] = $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* addAttachment
|
||||
*
|
||||
* @param string $filename
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addAttachment(string $filename): void {
|
||||
$this->option['attachments'][] = $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send(): bool {
|
||||
if (empty($this->option['to'])) {
|
||||
throw new \Exception('Error: E-Mail to required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['from'])) {
|
||||
throw new \Exception('Error: E-Mail from required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['sender'])) {
|
||||
throw new \Exception('Error: E-Mail sender required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['subject'])) {
|
||||
throw new \Exception('Error: E-Mail subject required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['text']) && empty($this->option['html'])) {
|
||||
throw new \Exception('Error: E-Mail message required!');
|
||||
}
|
||||
|
||||
return $this->adaptor->send();
|
||||
}
|
||||
}
|
109
system/library/mail/mail.php
Normal file
109
system/library/mail/mail.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Mail;
|
||||
/**
|
||||
* Class Mail
|
||||
*
|
||||
* Basic PHP mail class
|
||||
*/
|
||||
class Mail {
|
||||
protected array $option = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $option
|
||||
*/
|
||||
public function __construct(array &$option = []) {
|
||||
$this->option = &$option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send(): bool {
|
||||
if (is_array($this->option['to'])) {
|
||||
$to = implode(',', $this->option['to']);
|
||||
} else {
|
||||
$to = $this->option['to'];
|
||||
}
|
||||
|
||||
if (version_compare(phpversion(), '8.0', '>=') || substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
$eol = "\r\n";
|
||||
} else {
|
||||
$eol = PHP_EOL;
|
||||
}
|
||||
|
||||
$boundary = '----=_NextPart_' . md5(time());
|
||||
|
||||
$header = 'MIME-Version: 1.0' . $eol;
|
||||
$header .= 'Date: ' . date('D, d M Y H:i:s O') . $eol;
|
||||
$header .= 'From: =?UTF-8?B?' . base64_encode($this->option['sender']) . '?= <' . $this->option['from'] . '>' . $eol;
|
||||
|
||||
if (empty($this->option['reply_to'])) {
|
||||
$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->option['sender']) . '?= <' . $this->option['from'] . '>' . $eol;
|
||||
} else {
|
||||
$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->option['reply_to']) . '?= <' . $this->option['reply_to'] . '>' . $eol;
|
||||
}
|
||||
|
||||
$header .= 'Return-Path: ' . $this->option['from'] . $eol;
|
||||
$header .= 'X-Mailer: PHP/' . phpversion() . $eol;
|
||||
$header .= 'Content-Type: multipart/mixed; boundary="' . $boundary . '"' . $eol . $eol;
|
||||
|
||||
$message = '--' . $boundary . $eol;
|
||||
|
||||
if (empty($this->option['html'])) {
|
||||
$message .= 'Content-Type: text/plain; charset="utf-8"' . $eol;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . $eol . $eol;
|
||||
$message .= chunk_split(base64_encode($this->option['text']), 950) . $eol;
|
||||
} else {
|
||||
$message .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '_alt"' . $eol . $eol;
|
||||
$message .= '--' . $boundary . '_alt' . $eol;
|
||||
$message .= 'Content-Type: text/plain; charset="utf-8"' . $eol;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . $eol . $eol;
|
||||
|
||||
if (!empty($this->option['text'])) {
|
||||
$message .= chunk_split(base64_encode($this->option['text']), 950) . $eol;
|
||||
} else {
|
||||
$message .= chunk_split(base64_encode('This is a HTML email and your email client software does not support HTML email!'), 950) . $eol;
|
||||
}
|
||||
|
||||
$message .= '--' . $boundary . '_alt' . $eol;
|
||||
$message .= 'Content-Type: text/html; charset="utf-8"' . $eol;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . $eol . $eol;
|
||||
$message .= chunk_split(base64_encode($this->option['html']), 950) . $eol;
|
||||
$message .= '--' . $boundary . '_alt--' . $eol;
|
||||
}
|
||||
|
||||
if (!empty($this->option['attachments'])) {
|
||||
foreach ($this->option['attachments'] as $attachment) {
|
||||
if (is_file($attachment)) {
|
||||
$handle = fopen($attachment, 'r');
|
||||
|
||||
$content = fread($handle, filesize($attachment));
|
||||
|
||||
fclose($handle);
|
||||
|
||||
$message .= '--' . $boundary . $eol;
|
||||
$message .= 'Content-Type: application/octet-stream; name="' . basename($attachment) . '"' . $eol;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . $eol;
|
||||
$message .= 'Content-Disposition: attachment; filename="' . basename($attachment) . '"' . $eol;
|
||||
$message .= 'Content-ID: <' . urlencode(basename($attachment)) . '>' . $eol;
|
||||
$message .= 'X-Attachment-Id: ' . urlencode(basename($attachment)) . $eol . $eol;
|
||||
$message .= chunk_split(base64_encode($content), 950);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message .= '--' . $boundary . '--' . $eol;
|
||||
|
||||
ini_set('sendmail_from', $this->option['from']);
|
||||
|
||||
if (!empty($this->option['parameter'])) {
|
||||
return mail($to, '=?UTF-8?B?' . base64_encode($this->option['subject']) . '?=', $message, $header, $this->option['parameter']);
|
||||
} else {
|
||||
return mail($to, '=?UTF-8?B?' . base64_encode($this->option['subject']) . '?=', $message, $header);
|
||||
}
|
||||
}
|
||||
}
|
312
system/library/mail/smtp.php
Normal file
312
system/library/mail/smtp.php
Normal file
@ -0,0 +1,312 @@
|
||||
<?php
|
||||
/**
|
||||
* Basic SMTP mail class
|
||||
*/
|
||||
namespace Opencart\System\Library\Mail;
|
||||
/**
|
||||
* Class Smtp
|
||||
*/
|
||||
class Smtp {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $option = [];
|
||||
/**
|
||||
* @var array|int[]
|
||||
*/
|
||||
protected array $default = [
|
||||
'smtp_port' => 25,
|
||||
'smtp_timeout' => 5,
|
||||
'max_attempts' => 3,
|
||||
'verp' => false
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $option
|
||||
*/
|
||||
public function __construct(array &$option = []) {
|
||||
foreach ($this->default as $key => $value) {
|
||||
if (!isset($option[$key])) {
|
||||
$option[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->option = &$option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function send(): bool {
|
||||
if (empty($this->option['smtp_hostname'])) {
|
||||
throw new \Exception('Error: SMTP hostname required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['smtp_username'])) {
|
||||
throw new \Exception('Error: SMTP username required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['smtp_password'])) {
|
||||
throw new \Exception('Error: SMTP password required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['smtp_port'])) {
|
||||
throw new \Exception('Error: SMTP port required!');
|
||||
}
|
||||
|
||||
if (empty($this->option['smtp_timeout'])) {
|
||||
throw new \Exception('Error: SMTP timeout required!');
|
||||
}
|
||||
|
||||
if (is_array($this->option['to'])) {
|
||||
$to = implode(',', $this->option['to']);
|
||||
} else {
|
||||
$to = $this->option['to'];
|
||||
}
|
||||
|
||||
$boundary = '----=_NextPart_' . md5(time());
|
||||
|
||||
$header = 'MIME-Version: 1.0' . PHP_EOL;
|
||||
$header .= 'To: <' . $to . '>' . PHP_EOL;
|
||||
$header .= 'Subject: =?UTF-8?B?' . base64_encode($this->option['subject']) . '?=' . PHP_EOL;
|
||||
$header .= 'Date: ' . date('D, d M Y H:i:s O') . PHP_EOL;
|
||||
$header .= 'From: =?UTF-8?B?' . base64_encode($this->option['sender']) . '?= <' . $this->option['from'] . '>' . PHP_EOL;
|
||||
|
||||
if (empty($this->option['reply_to'])) {
|
||||
$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->option['sender']) . '?= <' . $this->option['from'] . '>' . PHP_EOL;
|
||||
} else {
|
||||
$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->option['reply_to']) . '?= <' . $this->option['reply_to'] . '>' . PHP_EOL;
|
||||
}
|
||||
|
||||
$header .= 'Return-Path: ' . $this->option['from'] . PHP_EOL;
|
||||
$header .= 'X-Mailer: PHP/' . phpversion() . PHP_EOL;
|
||||
$header .= 'Content-Type: multipart/mixed; boundary="' . $boundary . '"' . PHP_EOL . PHP_EOL;
|
||||
|
||||
$message = '--' . $boundary . PHP_EOL;
|
||||
|
||||
if (empty($this->option['html'])) {
|
||||
$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL;
|
||||
$message .= chunk_split(base64_encode($this->option['text']), 950) . PHP_EOL;
|
||||
} else {
|
||||
$message .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '_alt"' . PHP_EOL . PHP_EOL;
|
||||
$message .= '--' . $boundary . '_alt' . PHP_EOL;
|
||||
$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL;
|
||||
|
||||
if (!empty($this->option['text'])) {
|
||||
$message .= chunk_split(base64_encode($this->option['text']), 950) . PHP_EOL;
|
||||
} else {
|
||||
$message .= chunk_split(base64_encode('This is a HTML email and your email client software does not support HTML email!'), 950) . PHP_EOL;
|
||||
}
|
||||
|
||||
$message .= '--' . $boundary . '_alt' . PHP_EOL;
|
||||
$message .= 'Content-Type: text/html; charset="utf-8"' . PHP_EOL;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL . PHP_EOL;
|
||||
$message .= chunk_split(base64_encode($this->option['html']), 950) . PHP_EOL;
|
||||
$message .= '--' . $boundary . '_alt--' . PHP_EOL;
|
||||
}
|
||||
|
||||
if (!empty($this->option['attachments'])) {
|
||||
foreach ($this->option['attachments'] as $attachment) {
|
||||
if (is_file($attachment)) {
|
||||
$handle = fopen($attachment, 'r');
|
||||
|
||||
$content = fread($handle, filesize($attachment));
|
||||
|
||||
fclose($handle);
|
||||
|
||||
$message .= '--' . $boundary . PHP_EOL;
|
||||
$message .= 'Content-Type: application/octet-stream; name="' . basename($attachment) . '"' . PHP_EOL;
|
||||
$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL;
|
||||
$message .= 'Content-Disposition: attachment; filename="' . basename($attachment) . '"' . PHP_EOL;
|
||||
$message .= 'Content-ID: <' . urlencode(basename($attachment)) . '>' . PHP_EOL;
|
||||
$message .= 'X-Attachment-Id: ' . urlencode(basename($attachment)) . PHP_EOL . PHP_EOL;
|
||||
$message .= chunk_split(base64_encode($content), 950);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message .= '--' . $boundary . '--' . PHP_EOL;
|
||||
|
||||
if (substr($this->option['smtp_hostname'], 0, 3) == 'tls') {
|
||||
$hostname = substr($this->option['smtp_hostname'], 6);
|
||||
} else {
|
||||
$hostname = $this->option['smtp_hostname'];
|
||||
}
|
||||
|
||||
$handle = fsockopen($hostname, $this->option['smtp_port'], $errno, $errstr, $this->option['smtp_timeout']);
|
||||
|
||||
if ($handle) {
|
||||
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||
socket_set_timeout($handle, $this->option['smtp_timeout'], 0);
|
||||
}
|
||||
|
||||
while ($line = fgets($handle, 515)) {
|
||||
if (substr($line, 3, 1) == ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fputs($handle, 'EHLO ' . getenv('SERVER_NAME') . "\r\n");
|
||||
|
||||
$reply = '';
|
||||
|
||||
while ($line = fgets($handle, 515)) {
|
||||
$reply .= $line;
|
||||
|
||||
//some SMTP servers respond with 220 code before responding with 250. hence, we need to ignore 220 response string
|
||||
if (substr($reply, 0, 3) == 220 && substr($line, 3, 1) == ' ') {
|
||||
$reply = '';
|
||||
|
||||
continue;
|
||||
} elseif (substr($line, 3, 1) == ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (substr($reply, 0, 3) != 250) {
|
||||
throw new \Exception('Error: EHLO not accepted from server!');
|
||||
}
|
||||
|
||||
if (substr($this->option['smtp_hostname'], 0, 3) == 'tls') {
|
||||
fputs($handle, 'STARTTLS' . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 220, 'Error: STARTTLS not accepted from server!');
|
||||
|
||||
if (stream_socket_enable_crypto($handle, true, STREAM_CRYPTO_METHOD_TLS_CLIENT) !== true) {
|
||||
throw new \Exception('Error: TLS could not be established!');
|
||||
}
|
||||
|
||||
fputs($handle, 'EHLO ' . getenv('SERVER_NAME') . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 250, 'Error: EHLO not accepted from server!');
|
||||
}
|
||||
|
||||
if (!empty($this->option['smtp_username']) && !empty($this->option['smtp_password'])) {
|
||||
fputs($handle, 'AUTH LOGIN' . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 334, 'Error: AUTH LOGIN not accepted from server!');
|
||||
|
||||
fputs($handle, base64_encode($this->option['smtp_username']) . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 334, 'Error: Username not accepted from server!');
|
||||
|
||||
fputs($handle, base64_encode($this->option['smtp_password']) . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 235, 'Error: Password not accepted from server!');
|
||||
|
||||
} else {
|
||||
fputs($handle, 'HELO ' . getenv('SERVER_NAME') . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 250, 'Error: HELO not accepted from server!');
|
||||
}
|
||||
|
||||
if ($this->option['verp']) {
|
||||
fputs($handle, 'MAIL FROM: <' . $this->option['from'] . '>XVERP' . "\r\n");
|
||||
} else {
|
||||
fputs($handle, 'MAIL FROM: <' . $this->option['from'] . '>' . "\r\n");
|
||||
}
|
||||
|
||||
$this->handleReply($handle, 250, 'Error: MAIL FROM not accepted from server!');
|
||||
|
||||
if (!is_array($this->option['to'])) {
|
||||
fputs($handle, 'RCPT TO: <' . $this->option['to'] . '>' . "\r\n");
|
||||
|
||||
$reply = $this->handleReply($handle, false, 'RCPT TO [!array]');
|
||||
|
||||
if ((substr($reply, 0, 3) != 250) && (substr($reply, 0, 3) != 251)) {
|
||||
throw new \Exception('Error: RCPT TO not accepted from server!');
|
||||
}
|
||||
} else {
|
||||
foreach ($this->option['to'] as $recipient) {
|
||||
fputs($handle, 'RCPT TO: <' . $recipient . '>' . "\r\n");
|
||||
|
||||
$reply = $this->handleReply($handle, false, 'RCPT TO [array]');
|
||||
|
||||
if ((substr($reply, 0, 3) != 250) && (substr($reply, 0, 3) != 251)) {
|
||||
throw new \Exception('Error: RCPT TO not accepted from server!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fputs($handle, 'DATA' . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 354, 'Error: DATA not accepted from server!');
|
||||
|
||||
// According to rfc 821 we should not send more than 1000 including the CRLF
|
||||
$message = str_replace("\r\n", "\n", $header . $message);
|
||||
$message = str_replace("\r", "\n", $message);
|
||||
|
||||
$lines = explode("\n", $message);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
// see https://php.watch/versions/8.2/str_split-empty-string-empty-array
|
||||
$results = ($line === '') ? [''] : str_split($line, 998);
|
||||
|
||||
foreach ($results as $result) {
|
||||
fputs($handle, $result . "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
fputs($handle, '.' . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 250, 'Error: DATA not accepted from server!');
|
||||
|
||||
fputs($handle, 'QUIT' . "\r\n");
|
||||
|
||||
$this->handleReply($handle, 221, 'Error: QUIT not accepted from server!');
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
throw new \Exception('Error: ' . $errstr . ' (' . $errno . ')');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handleReply
|
||||
*
|
||||
* @param array $handle
|
||||
* @param bool $status_code
|
||||
* @param bool $error_text
|
||||
* @param int $counter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function handleReply($handle, $status_code = false, $error_text = false, $counter = 0) {
|
||||
$reply = '';
|
||||
|
||||
while (($line = fgets($handle, 515)) !== false) {
|
||||
$reply .= $line;
|
||||
|
||||
if (substr($line, 3, 1) == ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle slowish server responses (generally due to policy servers)
|
||||
if (!$line && empty($reply) && $counter < $this->option['max_attempts']) {
|
||||
sleep(1);
|
||||
|
||||
$counter++;
|
||||
|
||||
return $this->handleReply($handle, $status_code, $error_text, $counter);
|
||||
}
|
||||
|
||||
if ($status_code) {
|
||||
if (substr($reply, 0, 3) != $status_code) {
|
||||
throw new \Exception($error_text);
|
||||
}
|
||||
}
|
||||
|
||||
return $reply;
|
||||
}
|
||||
}
|
66
system/library/request.php
Normal file
66
system/library/request.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Request
|
||||
*/
|
||||
class Request {
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
public array $get = [];
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
public array $post = [];
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
public array $cookie = [];
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
public array $files = [];
|
||||
/**
|
||||
* @var array|mixed
|
||||
*/
|
||||
public array $server = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->get = $this->clean($_GET);
|
||||
$this->post = $this->clean($_POST);
|
||||
$this->cookie = $this->clean($_COOKIE);
|
||||
$this->files = $this->clean($_FILES);
|
||||
$this->server = $this->clean($_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function clean(mixed $data): mixed {
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
unset($data[$key]);
|
||||
|
||||
$data[$this->clean($key)] = $this->clean($value);
|
||||
}
|
||||
} else {
|
||||
$data = trim(htmlspecialchars($data, ENT_COMPAT, 'UTF-8'));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
145
system/library/response.php
Normal file
145
system/library/response.php
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Response
|
||||
*
|
||||
* Stores the response so the correct headers can go out before the response output is shown.
|
||||
*
|
||||
*/
|
||||
class Response {
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $headers = [];
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private int $level = 0;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $output = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $header
|
||||
*
|
||||
*/
|
||||
public function addHeader(string $header): void {
|
||||
$this->headers[] = $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Headers
|
||||
*
|
||||
* @param array
|
||||
*
|
||||
*/
|
||||
public function getHeaders(): array {
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $status
|
||||
*
|
||||
*/
|
||||
public function redirect(string $url, int $status = 302): void {
|
||||
header('Location: ' . str_replace(['&', "\n", "\r"], ['&', '', ''], $url), true, $status);
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Compression
|
||||
*
|
||||
* @param int $level
|
||||
*/
|
||||
public function setCompression(int $level): void {
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Output
|
||||
*
|
||||
* @param string $output
|
||||
*/
|
||||
public function setOutput(string $output): void {
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Output
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOutput(): string {
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress
|
||||
*
|
||||
* @param string $data
|
||||
* @param int $level
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function compress(string $data, int $level = 0): string {
|
||||
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)) {
|
||||
$encoding = 'gzip';
|
||||
}
|
||||
|
||||
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip') !== false)) {
|
||||
$encoding = 'x-gzip';
|
||||
}
|
||||
|
||||
if (!isset($encoding) || ($level < -1 || $level > 9)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (!extension_loaded('zlib') || ini_get('zlib.output_compression')) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (headers_sent()) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (connection_status()) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$this->addHeader('Content-Encoding: ' . $encoding);
|
||||
|
||||
return gzencode($data, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output
|
||||
*
|
||||
* Displays the set HTML output
|
||||
*/
|
||||
public function output(): void {
|
||||
if ($this->output) {
|
||||
$output = $this->level ? $this->compress($this->output, $this->level) : $this->output;
|
||||
|
||||
if (!headers_sent()) {
|
||||
foreach ($this->headers as $header) {
|
||||
header($header, true);
|
||||
}
|
||||
}
|
||||
|
||||
echo $output;
|
||||
}
|
||||
}
|
||||
}
|
122
system/library/session.php
Normal file
122
system/library/session.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Session
|
||||
*/
|
||||
class Session {
|
||||
/**
|
||||
* @var object|mixed
|
||||
*/
|
||||
protected object $adaptor;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $session_id;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public array $data = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(string $adaptor, \Opencart\System\Engine\Registry $registry) {
|
||||
$class = 'Opencart\System\Library\Session\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
if ($registry) {
|
||||
$this->adaptor = new $class($registry);
|
||||
} else {
|
||||
$this->adaptor = new $class();
|
||||
}
|
||||
|
||||
register_shutdown_function([&$this, 'close']);
|
||||
register_shutdown_function([&$this, 'gc']);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load session adaptor ' . $adaptor . ' session!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Session ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId(): string {
|
||||
return $this->session_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start
|
||||
*
|
||||
* Starts a session.
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return string Returns the current session ID.
|
||||
*/
|
||||
public function start(string $session_id = ''): string {
|
||||
if (!$session_id) {
|
||||
if (function_exists('random_bytes')) {
|
||||
$session_id = substr(bin2hex(random_bytes(26)), 0, 26);
|
||||
} else {
|
||||
$session_id = substr(bin2hex(openssl_random_pseudo_bytes(26)), 0, 26);
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match('/^[a-zA-Z0-9,\-]{22,52}$/', $session_id)) {
|
||||
$this->session_id = $session_id;
|
||||
} else {
|
||||
throw new \Exception('Error: Invalid session ID!');
|
||||
}
|
||||
|
||||
$this->data = $this->adaptor->read($session_id);
|
||||
|
||||
return $session_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close
|
||||
*
|
||||
* Writes the session data to storage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close(): void {
|
||||
$this->adaptor->write($this->session_id, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy
|
||||
*
|
||||
* Deletes the current session from storage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function destroy(): void {
|
||||
$this->data = [];
|
||||
|
||||
$this->adaptor->destroy($this->session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* GC
|
||||
*
|
||||
* Garbage Collection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function gc(): void {
|
||||
$this->adaptor->gc($this->session_id);
|
||||
}
|
||||
}
|
88
system/library/session/db.php
Normal file
88
system/library/session/db.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
CREATE TABLE IF NOT EXISTS `session` (
|
||||
`session_id` varchar(32) NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
`expire` datetime NOT NULL,
|
||||
PRIMARY KEY (`session_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
|
||||
*/
|
||||
namespace Opencart\System\Library\Session;
|
||||
/**
|
||||
* Class DB
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class DB {
|
||||
private object $db;
|
||||
private object $config;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->db = $registry->get('db');
|
||||
$this->config = $registry->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function read(string $session_id): array {
|
||||
$query = $this->db->query("SELECT `data` FROM `" . DB_PREFIX . "session` WHERE `session_id` = '" . $this->db->escape($session_id) . "' AND `expire` > '" . $this->db->escape(gmdate('Y-m-d H:i:s')) . "'");
|
||||
|
||||
if ($query->num_rows) {
|
||||
return (array)json_decode($query->row['data'], true);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* @param string $session_id
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write(string $session_id, array $data): bool {
|
||||
if ($session_id) {
|
||||
$this->db->query("REPLACE INTO `" . DB_PREFIX . "session` SET `session_id` = '" . $this->db->escape($session_id) . "', `data` = '" . $this->db->escape($data ? json_encode($data) : '') . "', `expire` = '" . $this->db->escape(gmdate('Y-m-d H:i:s', time() + $this->config->get('session_expire'))) . "'");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(string $session_id): bool {
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE `session_id` = '" . $this->db->escape($session_id) . "'");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GC
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function gc(): bool {
|
||||
if (round(rand(1, $this->config->get('session_divisor') / $this->config->get('session_probability'))) == 1) {
|
||||
$this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE `expire` < '" . $this->db->escape(gmdate('Y-m-d H:i:s', time())) . "'");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
83
system/library/session/file.php
Normal file
83
system/library/session/file.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Session;
|
||||
/**
|
||||
* Class File
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class File {
|
||||
private object $config;
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->config = $registry->get('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function read(string $session_id): array {
|
||||
$file = DIR_SESSION . 'sess_' . basename($session_id);
|
||||
|
||||
if (is_file($file)) {
|
||||
return json_decode(file_get_contents($file), true);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* @param string $session_id
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write(string $session_id, array $data): bool {
|
||||
file_put_contents(DIR_SESSION . 'sess_' . basename($session_id), json_encode($data));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function destroy(string $session_id): void {
|
||||
$file = DIR_SESSION . 'sess_' . basename($session_id);
|
||||
|
||||
if (is_file($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GC
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function gc(): void {
|
||||
if (round(rand(1, $this->config->get('session_divisor') / $this->config->get('session_probability'))) == 1) {
|
||||
$expire = time() - $this->config->get('session_expire');
|
||||
|
||||
$files = glob(DIR_SESSION . 'sess_*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file) && filemtime($file) < $expire) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
81
system/library/session/redis.php
Normal file
81
system/library/session/redis.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Session;
|
||||
/**
|
||||
* Class Redis
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Redis {
|
||||
private object $config;
|
||||
private object $redis;
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param object $registry
|
||||
*/
|
||||
public function __construct(\Opencart\System\Engine\Registry $registry) {
|
||||
$this->config = $registry->get('config');
|
||||
|
||||
try {
|
||||
$this->redis = new \Redis();
|
||||
$this->redis->pconnect(CACHE_HOSTNAME, CACHE_PORT);
|
||||
$this->prefix = CACHE_PREFIX . '.session.'; // session prefix to identify session keys
|
||||
} catch (\RedisException $e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function read(string $session_id): array {
|
||||
$data = $this->redis->get($this->prefix . $session_id);
|
||||
if (is_null($data) || empty($data))
|
||||
return [];
|
||||
return json_decode($data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write
|
||||
*
|
||||
* @param string $session_id
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function write(string $session_id, array $data): bool {
|
||||
if ($session_id) {
|
||||
$this->redis->set($this->prefix . $session_id, $data ? json_encode($data) : '', $this->config->get('session_expire'));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy
|
||||
*
|
||||
* @param string $session_id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function destroy(string $session_id): bool {
|
||||
$this->redis->unlink($this->prefix . $session_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GC
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function gc(): bool {
|
||||
// Redis will take care of Garbage Collection itself.
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
57
system/library/template.php
Normal file
57
system/library/template.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class Template
|
||||
*/
|
||||
class Template {
|
||||
/**
|
||||
* @var object|mixed
|
||||
*/
|
||||
private object $adaptor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
*
|
||||
*/
|
||||
public function __construct(string $adaptor) {
|
||||
$class = 'Opencart\System\Library\Template\\' . $adaptor;
|
||||
|
||||
if (class_exists($class)) {
|
||||
$this->adaptor = new $class();
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load template adaptor ' . $adaptor . '!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* addPath
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $directory
|
||||
*/
|
||||
public function addPath(string $namespace, string $directory = ''): void {
|
||||
$this->adaptor->addPath($namespace, $directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render(string $filename, array $data = [], string $code = ''): string {
|
||||
return $this->adaptor->render($filename, $data, $code);
|
||||
}
|
||||
}
|
94
system/library/template/template.php
Normal file
94
system/library/template/template.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Template;
|
||||
/**
|
||||
* Class Template
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Template {
|
||||
protected string $directory = '';
|
||||
protected array $path = [];
|
||||
|
||||
/**
|
||||
* addPath
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $directory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPath(string $namespace, string $directory = ''): void {
|
||||
if (!$directory) {
|
||||
$this->directory = $namespace;
|
||||
} else {
|
||||
$this->path[$namespace] = $directory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render(string $filename, array $data = [], string $code = ''): string {
|
||||
if (!$code) {
|
||||
$file = $this->directory . $filename . '.tpl';
|
||||
|
||||
$namespace = '';
|
||||
|
||||
$parts = explode('/', $filename);
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (!$namespace) {
|
||||
$namespace .= $part;
|
||||
} else {
|
||||
$namespace .= '/' . $part;
|
||||
}
|
||||
|
||||
if (isset($this->path[$namespace])) {
|
||||
$file = $this->path[$namespace] . substr($filename, strlen($namespace) + 1) . '.tpl';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($file) && is_file($file)) {
|
||||
$code = file_get_contents($file);
|
||||
} else {
|
||||
throw new \Exception('Error: Could not load template ' . $filename . '!');
|
||||
}
|
||||
}
|
||||
|
||||
if ($code) {
|
||||
ob_start();
|
||||
|
||||
extract($data);
|
||||
|
||||
include($this->compile($filename, $code));
|
||||
|
||||
return ob_get_clean();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile(string $filename, string $code): string {
|
||||
$file = DIR_CACHE . 'template/' . hash('md5', $filename . $code) . '.php';
|
||||
|
||||
if (!is_file($file)) {
|
||||
file_put_contents($file, $code, LOCK_EX);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
123
system/library/template/twig.php
Normal file
123
system/library/template/twig.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
namespace Opencart\System\Library\Template;
|
||||
/**
|
||||
* Class Twig
|
||||
*
|
||||
* @package
|
||||
*/
|
||||
class Twig {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $root;
|
||||
/**
|
||||
* @var object|\Twig\Loader\FilesystemLoader
|
||||
*/
|
||||
protected object $loader;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $directory;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected array $path = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $adaptor
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
// Unfortunately, we have to set the web root directory as the base since Twig confuses which template cache to use.
|
||||
$this->root = substr(DIR_OPENCART, 0, -1);
|
||||
|
||||
// We have to add the C directory as the base directory because twig can only accept the first namespace/,
|
||||
// rather than a multiple namespace system, which took me less than a minute to write. If symphony is like
|
||||
// this, then I have no idea why people use the framework.
|
||||
$this->loader = new \Twig\Loader\FilesystemLoader('/', $this->root);
|
||||
}
|
||||
|
||||
/**
|
||||
* addPath
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param string $directory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addPath(string $namespace, string $directory = ''): void {
|
||||
if (!$directory) {
|
||||
$this->directory = $namespace;
|
||||
} else {
|
||||
$this->path[$namespace] = $directory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @param string $filename
|
||||
* @param array $data
|
||||
* @param string $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render(string $filename, array $data = [], string $code = ''): string {
|
||||
$file = $this->directory . $filename . '.twig';
|
||||
|
||||
/*
|
||||
* FYI all the Twig lovers out there!
|
||||
* The Twig syntax is good, but the implementation and the available methods is a joke!
|
||||
*
|
||||
* All the Symfony developer has done is create a garbage frame work putting 3rd party scripts into DI containers.
|
||||
* The Twig syntax he ripped off from Jinja and Django templates then did a garbage implementation!
|
||||
*
|
||||
* The fact that this system cache is just compiling php into more php code instead of html is a disgrace!
|
||||
*/
|
||||
|
||||
$namespace = '';
|
||||
|
||||
$parts = explode('/', $filename);
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (!$namespace) {
|
||||
$namespace .= $part;
|
||||
} else {
|
||||
$namespace .= '/' . $part;
|
||||
}
|
||||
|
||||
if (isset($this->path[$namespace])) {
|
||||
$file = $this->path[$namespace] . substr($filename, strlen($namespace) + 1) . '.twig';
|
||||
}
|
||||
}
|
||||
|
||||
// We have to remove the root web directory.
|
||||
$file = substr($file, strlen($this->root) + 1);
|
||||
|
||||
if ($code) {
|
||||
// render from modified template code
|
||||
$loader = new \Twig\Loader\ArrayLoader([$file => $code]);
|
||||
} else {
|
||||
$loader = $this->loader;
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize Twig environment
|
||||
$config = [
|
||||
'charset' => 'utf-8',
|
||||
'autoescape' => false,
|
||||
'debug' => false,
|
||||
'auto_reload' => true,
|
||||
'cache' => DIR_CACHE . 'template/'
|
||||
];
|
||||
|
||||
$twig = new \Twig\Environment($loader, $config);
|
||||
|
||||
return $twig->render($file, $data);
|
||||
} catch (Twig_Error_Syntax $e) {
|
||||
throw new \Exception('Error: Could not load template ' . $filename . '!');
|
||||
}
|
||||
}
|
||||
}
|
76
system/library/url.php
Normal file
76
system/library/url.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* @package OpenCart
|
||||
* @author Daniel Kerr
|
||||
* @copyright Copyright (c) 2005 - 2022, OpenCart, Ltd. (https://www.opencart.com/)
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @author Daniel Kerr
|
||||
* @see https://www.opencart.com
|
||||
*/
|
||||
namespace Opencart\System\Library;
|
||||
/**
|
||||
* Class URL
|
||||
*/
|
||||
class Url {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $url;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $rewrite = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $url
|
||||
*/
|
||||
public function __construct(string $url) {
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* addRewrite
|
||||
*
|
||||
* Add a rewrite method to the URL system
|
||||
*
|
||||
* @param object $rewrite
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addRewrite(\Opencart\System\Engine\Controller $rewrite): void {
|
||||
$this->rewrite[] = $rewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a URL
|
||||
*
|
||||
* @param string $route
|
||||
* @param string|array $args
|
||||
* @param bool $js
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function link(string $route, string|array $args = '', bool $js = false): string {
|
||||
$url = $this->url . 'index.php?route=' . $route;
|
||||
|
||||
if ($args) {
|
||||
if (is_array($args)) {
|
||||
$url .= '&' . http_build_query($args);
|
||||
} else {
|
||||
$url .= '&' . trim($args, '&');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->rewrite as $rewrite) {
|
||||
$url = $rewrite->rewrite($url);
|
||||
}
|
||||
|
||||
if (!$js) {
|
||||
return str_replace('&', '&', $url);
|
||||
} else {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user