Skip to content

Instantly share code, notes, and snippets.

@Acen
Created January 16, 2017 05:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Acen/9658e59d6f12c652639345c6328c77e9 to your computer and use it in GitHub Desktop.
Save Acen/9658e59d6f12c652639345c6328c77e9 to your computer and use it in GitHub Desktop.
Convergence Codi -> BigCommerce with Laravel
<?php
namespace App\Core;
use \Exception;
use Carbon\Carbon;
use League\Csv\Reader;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Bigcommerce\Api\Client as BigCommerceClient;
class CategoryMatcher
{
// Codi/Infusion
private $level0; // Root Categories
private $level1; // Sub Categories
private $level2; // Product Groups
// BigCommerce Categories
private $bigcommerce_categories;
/*
* @var bool $force
*
* @return void
*/
function __construct($force = false)
{
if(!$force) {
$this->level0 = $this->getCodiCategories(0);
$this->level1 = $this->getCodiCategories(1);
$this->level2 = $this->getCodiCategories(2);
$this->bigcommerce_categories = $this->getBigCommerceCategories();
}else{
$this->level0 = $this->getCodiCategories(0, true);
$this->level1 = $this->getCodiCategories(1, true);
$this->level2 = $this->getCodiCategories(2, true);
$this->bigcommerce_categories = $this->getBigCommerceCategories(true);
}
}
/**
* Get BigCommerce Category IDs from Category Names.
*
* @var object $product
*
* @return array|bool
* @throws Exception
*/
public function getCategoryIDs($product = null)
{
if($product != null && isset($product)){
$category_names = $this->getCategoryNames($product);
$category_ids = array();
if($category_names && is_array($category_names)){
foreach($category_names as $category_name){
$bigcommerce_categories = $this->executeSearch($this->bigcommerce_categories, $category_name);
if($bigcommerce_categories) {
$category_ids[] = $bigcommerce_categories;
}
}
return $category_ids;
}
}else{
throw new Exception(
"Bad request. Please specify Infusion/Codi product.",
500
);
}
}
/**
* Get BigCommerce Category Names for Infusion/Codi Product.
*
* @var object $product
*
* @return array|bool
* @throws Exception
*/
public function getCategoryNames($product = null)
{
if($product != null && isset($product)){
if(isset($product->categories)){
$categories = explode(',', $product->categories);
$this->trim_spaces($categories);
foreach($categories as $key => $category){
$category_name = $this->getCategoryName($category);
if($category_name){
$category_names[] = $category_name;
}
}
$this->trim_spaces($category_names);
return $category_names;
}else{
return false;
}
}else{
throw new Exception(
"Bad request. Please specify Infusion/Codi product.",
500
);
}
}
/**
* Get categories that exist in BigCommerce, but not Codi.
*
* @var Integer $mode
*
* @return array|bool
* @throws \Exception
*/
public function getMissingCategories($mode = 0)
{
switch($mode){
case 0:
$source = $this->bigcommerce_categories;
$target = $this->mergeCodiCategories();
$key = 'description';
break;
case 1:
$source = $this->mergeCodiCategories();
$target = $this->bigcommerce_categories;
break;
default:
throw new \Exception(
"Bad request.\r\n0 = Show missing from Codi.\r\n1 = Show missing from BigCommerce.",
400
);
}
$results = array();
foreach($source as $item){
if(isset($key)) {
$search_results = $this->executeSearch($target, $item, $key);
if(!$search_results){
$results[] = $item;
}
}else{
$search_results = $this->executeSearch($target, $item['description']);
if(!$search_results){
$results[] = $item['description'];
}
}
}
return $results;
}
private function mergeCodiCategories()
{
$codi_categories = collect($this->level0);
$codi_categories = $codi_categories->merge($this->level1->toArray());
$codi_categories = $codi_categories->merge($this->level2->toArray());
return $codi_categories;
}
/**
* Get BigCommerce Category Name from 'categorycode'.
*
* @var string
*
* @return string|bool
*/
private function getCategoryName($category)
{
$search_level2 = $this->executeSearch($this->level2, $category, 'categorycode');
if($search_level2){
return $this->level2[$search_level2]['description'];
}else{
$search_level1 = $this->executeSearch($this->level1, $category, 'categorycode');
if($search_level1){
return $this->level1[$search_level1]['description'];
}else{
$search_level0 = $this->executeSearch($this->level0, $category, 'categorycode');
if($search_level0){
return $this->level0[$search_level0]['description'];
}else{
return false;
}
}
}
}
/**
* Execute search on collection.
*
* @var Collection $haystack
* @var string $needle
* @var string $key
*
* @return string
*/
public function executeSearch(Collection $haystack, $needle, $key = null)
{
if($key){
$search_query = $haystack->search(function($item) use ($needle, $key){
return $item[$key] == $needle;
});
}else{
$search_query = $haystack->search(function($item) use ($needle){
return $item == $needle;
});
}
return $search_query;
}
/**
* Return data from CSVs.
*
* @var integer $level
*
* @return array
*/
private function loadFromCSVs($level)
{
$reader = Reader::createFromString(
Storage::disk('local')
->get('categories/level' . ($level + 1) . '.csv'));
$categories = iterator_to_array($reader->fetchAssoc(0));
$this->trim_spaces($categories);
Cache::forever('level' . $level, $categories);
return $categories;
}
/**
* Gets Codi/Infusion Categories.
*
* @var int $level
* @var bool $force
*
* @return Collection
* @throws Exception
*/
private function getCodiCategories($level = false, $force = false)
{
if($level !== false){
if($force){
return collect($this->loadFromCSVs($level));
}else{
if(Cache::has('level' . $level)){
return collect(Cache::get('level' . $level));
}else {
return collect($this->loadFromCSVs($level));
}
}
}else{
throw new Exception(
"Bad request. Please specify a valid level. [0, 1, 2].",
503
);
}
}
/**
* Gets BigCommerce Categories.
*
* @return Collection
*/
private function getBigCommerceCategories($force = false)
{
if($force){
return collect($this->fetchBigCommerceCategories());
}else{
if(Cache::has('bigcommerce_categories')) {
return collect(Cache::get('bigcommerce_categories'));
}else {
return collect($this->fetchBigCommerceCategories());
}
}
}
/**
* Fetches BigCommerce Categories from API.
*
* @return array
*/
private function fetchBigCommerceCategories()
{
BigCommerceClient::configure(array(
'store_url' => getenv('BIGCOMMERCE_STORE_URL'),
'username' => getenv('BIGCOMMERCE_USERNAME'),
'api_key' => getenv('BIGCOMMERCE_TOKEN')
));
$response = BigCommerceClient::getCategories(['limit' => 250]);
$formatted_response = array();
foreach($response as $fields){
$formatted_response[] = $fields->fields;
}
$categories = array();
foreach($formatted_response as $category){
$categories[$category->id] = $category->name;
}
$this->trim_spaces($categories);
Cache::put(
'bigcommerce_categories',
$categories,
Carbon::now()->addHour()
);
return $categories;
}
/**
* Trims array values, removes empty values.
*
* @var &array
*
*/
private function trim_spaces(&$array){
if(is_array($array)) {
foreach ($array as $key => &$value) {
is_array($value) ? $this->trim_spaces($value) : $value = trim($value);
if (empty($value)) {
unset($array[$key]);
} else {
unset($value);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment