etsy-1.0.0-alpha3/modules/etsy_shop/etsy_shop.module
modules/etsy_shop/etsy_shop.module
<?php
use \Drupal\etsy\EtsyService;
use \Drupal\node\NodeInterface;
use \Drupal\taxonomy\Entity\Term;
/**
* Implements hook_help().
*/
function etsy_shop_help($route_name, \Drupal\Core\Routing\RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.etsy_shop':
return t('
<h3>About</h3>
<p><em>@todo</em> We need a description here.</p>
');
}
}
/**
* Implements hook_cron().
*
* @return void
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
function etsy_shop_cron() {
/**
* @var Drupal\etsy\EtsyService
*/
$etsyApi = \Drupal::service('etsy.api');
_etsy_shop_cron_process_sections($etsyApi);
_etsy_shop_cron_process_listings($etsyApi);
}
/**
* Implements hook_theme().
*/
function etsy_shop_theme($existing, $type, $theme, $path) {
return [
'etsy_price' => [
'variables' => [
'amount' => NULL,
'symbol' => NULL,
'currency_code' => NULL,
]
],
'node__etsy_listing__etsy_store_listing' => [
'template' => 'node--etsy-listing--etsy-store-listing',
'base hook' => 'node'
],
'node__etsy_listing' => [
'template' => 'node--etsy-listing',
'base hook' => 'node'
],
];
}
/**
* Implements hook_preprocess_field().
*
* @param array $variables
* @param string $hook
*
* @return void
*/
function etsy_shop_preprocess_field(&$variables, $hook) {
switch ($variables['field_name'] ) {
case 'field_etsy_when_made':
// There will only be one value.
break;
default:
// do nothing.
}
// if ( $variables['field_name'] == 'field_etsy_image' && $variables['element']['#bundle'] == 'etsy_listing' ) {
// foreach($variables['items'] as $key => $value ) {
// $variables['items'][$key]['content']['#alt'] = $variables['element']['#object']->label();
// $variables['items'][$key]['content']['#title'] = $variables['element']['#object']->label();
// }
// }
}
/**
* Currencies supported by Etsy.
*
* @return array[]
*/
function etsy_shop_supported_currencies() {
return [
'USD' => ['symbol' => '$', 'text' => t('United States Dollar')],
'CAD' => ['symbol' => '$', 'text' => t('Canadian Dollar')],
'EUR' => ['symbol' => '€', 'text' => t('Euro')],
'GBP' => ['symbol' => '£', 'text' => t('British Pound')],
'AUD' => ['symbol' => '$', 'text' => t('Australian Dollar')],
'JPY' => ['symbol' => '¥', 'text' => t('Japanese Yen')],
'CNY' => ['symbol' => '¥', 'text' => t('Chinese Yuan')],
'CZK' => ['symbol' => 'Kč', 'text' => t('Czech Koruna')],
'DKK' => ['symbol' => 'kr', 'text' => t('Danish Krone')],
'HKD' => ['symbol' => '$', 'text' => t('Hong Kong Dollar')],
'HUF' => ['symbol' => 'Ft', 'text' => t('Hungarian Forint')],
'INR' => ['symbol' => '₹', 'text' => t('Indian Rupee')],
'IDR' => ['symbol' => 'Rp', 'text' => t('Indonesian Rupiah')],
'ILS' => ['symbol' => '₪', 'text' => t('Israeli Shekel')],
'MYR' => ['symbol' => 'RM', 'text' => t('Malaysian Ringgit')],
'MXN' => ['symbol' => '$', 'text' => t('Mexican Peso')],
'MAD' => ['symbol' => 'DH', 'text' => t('Moroccan Dirham')],
'NZD' => ['symbol' => '$', 'text' => t('New Zealand Dollar')],
'NOK' => ['symbol' => 'kr', 'text' => t('Norwegian Krone')],
'PHP' => ['symbol' => '₱', 'text' => t('Philippine Peso')],
'SGD' => ['symbol' => '$', 'text' => t('Singapore Dollar')],
'VND' => ['symbol' => '₫', 'text' => t('Vietnamese Dong')],
'ZAR' => ['symbol' => 'R', 'text' => t('South African Rand')],
'SEK' => ['symbol' => 'kr', 'text' => t('Swedish Krona')],
'CHF' => ['symbol' => '', 'text' => t('Swiss Franc')],
'THB' => ['symbol' => '฿', 'text' => t('Thai Baht')],
'TWD' => ['symbol' => 'NT$', 'text' => t('Taiwan New Dollar')],
'TRY' => ['symbol' => '₺', 'text' => t('Turkish Lira')],
'PLN' => ['symbol' => 'zł', 'text' => t('Polish Zloty')],
'BRL' => ['symbol' => 'R$', 'text' => t('Brazilian Real')],
];
}
/**
* Processes Etsy sections from cron runs.
*
* @param \Drupal\etsy\EtsyService $api
*
* @return void
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
function _etsy_shop_cron_process_sections(EtsyService $api) {
// Get sections for the configured store.
if ( $sections = $api->getShopSections() ) {
try {
$sectionStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
} catch (\Exception $e ) {
\Drupal::logger('etsy_shop')->error($e->getMessage());
return;
}
if ( $sections->count > 0 ) {
foreach( $sections->results as $row ) {
$props = [
'vid' => 'etsy_section',
'field_shop_section_id' => $row->shop_section_id
];
$existing = $sectionStorage->loadByProperties($props);
if ( count($existing) > 0 ) {
/**
* @var Drupal\taxonomy\Entity\Term
*/
$term = reset($existing);
$term->name = $row->title;
$term->field_shop_section_rank = $row->rank;
$term->field_shop_user_id = $row->user_id;
$term->save();
}
else {
$props = [
'vid' => 'etsy_section',
'name' => $row->title,
'field_shop_section_id' => $row->shop_section_id,
'field_shop_section_rank' => $row->rank,
'field_shop_user_id' => $row->user_id
];
$term = $sectionStorage->create($props);
$term->save();
}
}
}
}
else {
\Drupal::logger('etsy_shop')->error(t('Cron: Failed to retrieve Etsy sections.'));
}
}
/**
* @param \Drupal\etsy\EtsyService $api
*
* @return void
*/
function _etsy_shop_cron_process_listings(EtsyService $api) {
$limit = 100;
if ( $listings = $api->getListingsByShop($limit, 0, [EtsyService::INCLUDES_IMAGES, EtsyService::INCLUDE_VIDEOS]) ) {
try {
$nodeStorage = \Drupal::entityTypeManager()->getStorage('node');
} catch (\Exception $e ) {
\Drupal::logger('etsy_shop')->error($e->getMessage());
return;
}
// Keep track of the number of listings for logging.
$new = $updated = $removed = [];
foreach( $listings->results as $listing ) {
$properties = [
'type' => 'etsy_listing',
'field_etsy_listing_id' => $listing->listing_id
];
$node = $nodeStorage->loadByProperties($properties);
if ( count($node) ) {
// Update existing listing.
$node = reset($node);
if ($node->get('field_etsy_updated_timestamp')->value != $listing->updated_timestamp ) {
_etsy_store_listing_node($listing, $node);
}
$updated[] = $listing->listing_id;
}
else {
// New listing
$values = [
'type' => 'etsy_listing',
];
$node = $nodeStorage->create($values);
_etsy_store_listing_node($listing, $node);
$new[] = $listing->listing_id;
}
}
// Remove any listings that were not in the latest API data.
$existing = array_merge($new, $updated);
$ids = $nodeStorage->getQuery()
->accessCheck(FALSE)
->condition('type', 'etsy_listing')
->condition('field_etsy_listing_id', $existing, 'NOT IN')
->execute();
$nodes = $nodeStorage->loadMultiple($ids);
if ( $nodes ) {
$removed = array_keys($nodes);
$nodeStorage->delete($nodes);
}
$data = [
'@new' => count($new),
'@updated' => count($updated),
'@removed' => count($removed)
];
\Drupal::logger('etsy_shop')->info('Etsy shop import imported @new new listings, updated @updated listings, and removed @removed listings.', $data);
}
else {
\Drupal::logger('etsy_shop')->error(t('Cron: Failed to retrieve Etsy listings.'));
}
}
/**
* Utility function to populate a NodeInterface object with Etsy listing data.
*
* @param \stdClass $listing
* @param \Drupal\node\NodeInterface $node
* @param bool $doSave
*
* @return void
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _etsy_store_listing_node(\stdClass $listing, NodeInterface &$node, bool $doSave=true) {
$termStorage = NULL;
try {
$termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
} catch (\Exception $e ) {
\Drupal::logger('etsy_shop')->error( $e->getMessage() );
}
$node->setTitle($listing->title);
$node->set('body', ['value' => $listing->description, 'format' => 'plain_text']);
$node->set('field_etsy_dimension_unit', $listing->item_dimensions_unit);
$node->set('field_etsy_url', $listing->url);
$node->set('field_etsy_featured', $listing->featured_rank);
$node->set('field_etsy_has_variations', $listing->has_variations);
$images = [];
foreach( $listing->images as $image ) {
$images[] = $image->url_fullxfull;
}
$node->set('field_etsy_image', $images);
$node->set('field_etsy_is_customizable', $listing->is_customizable);
$node->set('field_etsy_is_personalizable', $listing->is_personalizable);
$node->set('field_etsy_is_private', $listing->is_private);
$node->set('field_etsy_is_supply', $listing->is_supply);
$node->set('field_etsy_is_taxable', $listing->is_taxable);
$node->set('field_etsy_item_height', $listing->item_height);
$node->set('field_etsy_item_length', $listing->item_length);
$node->set('field_etsy_item_weight', $listing->item_weight);
$node->set('field_etsy_weight_unit', $listing->item_weight_unit);
$node->set('field_etsy_item_width', $listing->item_width);
$node->set('field_etsy_lang', $listing->language);
$node->set('field_etsy_listing_id', $listing->listing_id);
$node->set('field_etsy_listing_type', $listing->listing_type);
$materials = _etsy_shop_process_terms('etsy_materials', $listing->materials);
$node->set('field_etsy_materials', $materials);
$node->set('field_etsy_non_taxable', $listing->non_taxable);
$node->set('field_etsy_num_favorers', $listing->num_favorers);
$node->set('field_etsy_pers_instructions', $listing->personalization_instructions);
$node->set('field_etsy_pers_char_count_max', $listing->personalization_char_count_max);
$node->set('field_etsy_personalization_req', $listing->personalization_is_required);
$node->set('field_etsy_processing_max', $listing->processing_max);
$node->set('field_etsy_processing_min', $listing->processing_min);
$node->set('field_etsy_listing_quantity', $listing->quantity);
$node->set('field_etsy_return_policy_id', $listing->return_policy_id);
$node->set('field_etsy_price', ['amount' => $listing->price->amount, 'divisor' => $listing->price->divisor, 'currency_code' => $listing->price->currency_code]);
$sectionId = NULL;
if ( !is_null($termStorage) && !empty($listing->shop_section_id) ) {
if( $term = $termStorage->loadByProperties(['vid' => 'etsy_section', 'field_shop_section_id' => $listing->shop_section_id]) ) {
/**
* @var Drupal\taxonomy\Entity\Term
*/
$term = reset($term);
$sectionId = $term->id();
}
}
$node->set('field_etsy_shop_section', $sectionId);
$node->set('field_etsy_ship_profile_id', $listing->shipping_profile_id);
$node->set('field_etsy_shop_id', $listing->shop_id);
$node->set('field_etsy_autorenew', $listing->should_auto_renew);
$tags = _etsy_shop_process_terms('tags', $listing->tags);
$node->set('field_tags', $tags);
$node->set('field_etsy_user_id', $listing->user_id);
$node->set('field_etsy_views', $listing->views);
if ( preg_match('/^before_.*$/', $listing->when_made) === 1 ) {
$listing->when_made = ucfirst(str_replace('_', ' ', $listing->when_made));
} elseif ( preg_match('/^\d{1,4}_\d{1,4}$/', $listing->when_made) === 1) {
$listing->when_made = str_replace('_', ' - ', $listing->when_made);
} elseif ( $listing->when_made === 'made_to_order' ) {
$listing->when_made = t('Made to order');
}
$node->set('field_etsy_when_made', $listing->when_made);
$node->set('field_etsy_who_made_it', $listing->who_made);
if ( $node->isNew() ) {
$node->setCreatedTime($listing->created_timestamp);
}
$node->set('field_etsy_created_timestamp', $listing->created_timestamp);
$node->set('field_etsy_updated_timestamp', $listing->updated_timestamp);
if ( $listing->state === 'active' ) {
$node->setPublished();
}
else {
$node->setUnpublished();
}
$node->setOwnerId(1);
if ( $doSave ) {
$node->save();
}
}
/**
* Processes the Etsy material strings into taxonomy term ID's.
*
* @param string $vocabulary Vocabulary to check for terms.
* @param mixed $terms Array of term names
*
* @return array
*/
function _etsy_shop_process_terms($vocabulary, $terms) {
$termStorage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
$tids = [];
if ( is_array($terms) ) {
foreach ( $terms as $termString ) {
if ( $term = $termStorage->loadByProperties(['name' => $termString]) ) {
/**
* @var Drupal\taxonomy\Entity\Term
*/
$term = reset($term);
}
else {
$term = $termStorage->create(['vid' => $vocabulary, 'name' => $termString]);
$term->save();
}
$tids[] = $term->id();
}
}
return $tids ?? NULL;
}