Stores the uploaded CSV file containing the coupon codes

@param \Aimeos\MShop\Coupon\Item\Iface $item Coupon item object
@param array $files File upload array including the PSR-7 file upload objects
488337
protected function storeFile( \Aimeos\MShop\Coupon\Item\Iface $item, array $files )
	{
		$file = $this->getValue( $files, 'code/file' );

		if( $file == null || $file->getError() === UPLOAD_ERR_NO_FILE ) {
			return;
		}

		$this->checkFileUpload( $file );

		$context = $this->getContext();
		$fs = $context->getFilesystemManager()->get( 'fs-import' );
		$dir = 'couponcode/' . $context->getLocale()->getSite()->getCode();

		if( $fs->isdir( $dir ) === false ) {
			$fs->mkdir( $dir );
		}

		$fs->writes( $dir . '/' . $item->getId() . '.csv', $file->getStream()->detach() );
	}
851817
protected function _saveSubProducts( array $items )
	{
		$context = $this->_getContext();
		$default = array( 'attribute', 'price', 'text', 'product' );
		$domains = $context->getConfig()->get( 'mshop/catalog/manager/index/default/domains', $default );
		$size = $context->getConfig()->get( 'mshop/catalog/manager/index/default/chunksize', 1000 );

		$manager = MShop_Factory::createManager( $context, 'product' );
		$search = $manager->createSearch( true );
		$search->setSortations( array( $search->sort( '+', 'product.id' ) ) );
		$search->setSlice( 0, $size );
		$defaultConditions = $search->getConditions();

		$prodList = array();
		$numSubProducts = 0;

		foreach( $items as $id => $product )
		{
			foreach( $product->getRefItems( 'product', null, 'default' ) as $subId => $subItem )
			{
				$prodList[$subId] = $id;
				$numSubProducts++;
			}

			if( $numSubProducts >= $size )
			{
				$expr = array(
					$search->compare( '==', 'product.id', array_keys( $prodList ) ),
					$defaultConditions,
				);
				$search->setConditions( $search->combine( '&&', $expr ) );

				$this->_saveSubProductsChunk( $search, $domains, $prodList, $size );

				$prodList = array();
				$numSubProducts = 0;
			}
		}

		if( $numSubProducts > 0 )
		{
			$expr = array(
				$search->compare( '==', 'product.id', array_keys( $prodList ) ),
				$defaultConditions,
			);
			$search->setConditions( $search->combine( '&&', $expr ) );

			$this->_saveSubProductsChunk( $search, $domains, $prodList, $size );
		}
	}
361306
protected function checkLocale( \Aimeos\MShop\Locale\Item\Iface $locale, $type )
	{
		$errors = [];
		$context = $this->getContext();
		$session = $context->getSession();

		$localeStr = $session->get( 'aimeos/basket/locale' );
		$localeKey = $locale->getSite()->getCode() . '|' . $locale->getLanguageId() . '|' . $locale->getCurrencyId();

		if( $localeStr !== null && $localeStr !== $localeKey )
		{
			$locParts = explode( '|', $localeStr );
			$locSite = ( isset( $locParts[0] ) ? $locParts[0] : '' );
			$locLanguage = ( isset( $locParts[1] ) ? $locParts[1] : '' );
			$locCurrency = ( isset( $locParts[2] ) ? $locParts[2] : '' );

			$localeManager = \Aimeos\MShop::create( $context, 'locale' );
			$locale = $localeManager->bootstrap( $locSite, $locLanguage, $locCurrency, false );

			$context = clone $context;
			$context->setLocale( $locale );

			$manager = \Aimeos\MShop\Order\Manager\Factory::create( $context )->getSubManager( 'base' );
			$basket = $manager->getSession( $type )->off();

			$this->copyAddresses( $basket, $errors, $localeKey );
			$this->copyServices( $basket, $errors );
			$this->copyProducts( $basket, $errors, $localeKey );
			$this->copyCoupons( $basket, $errors, $localeKey );

			$manager->setSession( $basket, $type );
		}

		$session->set( 'aimeos/basket/locale', $localeKey );
	}
1185898
protected function setUploadedFiles(array &$files)
    {
        $isUploadedFiles = ($files === $_FILES);
        
        $this->files =& $files;
        $this->uploadedFiles = $this->groupUploadedFiles($files, null, $isUploadedFiles);
    }
1239184
protected function createNodeArray( \Aimeos\MShop\Locale\Item\Site\Iface $item )
	{
		$result = $item->toArray( true );

		if( method_exists( $item, 'getChildren' ) )
		{
			foreach( $item->getChildren() as $child ) {
				$result['children'][] = $this->createNodeArray( $child );
			}
		}

		return (object) $result;
	}
408956
protected function addCache( \Aimeos\MShop\Context\Item\Iface $context )
	{
		$cache = new \Aimeos\MAdmin\Cache\Proxy\Standard( $context );

		return $context->setCache( $cache );
	}
291025
protected function storeToStashFromArray(array $items)
    {
        $items = $this->mapStashStorageItems($items, null);

        $this->items = array_replace($this->items, $items);
    }
977290
protected function _saveAttributeTexts( array $items )
	{
		$prodIds = array();

		foreach( $items as $item )
		{
			foreach( $item->getRefItems( 'attribute', null, 'default' ) as $attrItem ) {
				$prodIds[$attrItem->getId()][] = $item->getId();
			}
		}

		if( empty( $prodIds ) ) { return; }


		$attrManager = MShop_Factory::createManager( $this->_getContext(), 'attribute' );
		$search = $attrManager->createSearch(true);
		$expr = array(
			$search->compare( '==', 'attribute.id', array_keys( $prodIds ) ),
			$search->getConditions()
		);
		$search->setConditions( $search->combine( '&&', $expr ) );
		$search->setSlice( 0, 0x7fffffff );

		$attributeItems = $attrManager->searchItems( $search, array( 'text' ) );


		$context = $this->_getContext();
		$locale = $context->getLocale();
		$siteid = $context->getLocale()->getSiteId();
		$editor = $context->getEditor();
		$date = date( 'Y-m-d H:i:s' );


		$dbm = $context->getDatabaseManager();
		$dbname = $this->_getResourceName();
		$conn = $dbm->acquire( $dbname );

		try
		{
			$stmt = $this->_getCachedStatement( $conn, 'mshop/catalog/manager/index/text/default/item/insert' );

			foreach( $attributeItems as $id => $item )
			{
				$listTypes = array();
				foreach( $item->getListItems( 'text', 'default' ) as $listItem ) {
					$listTypes[ $listItem->getRefId() ][] = $listItem->getType();
				}

				foreach( $item->getRefItems( 'text' ) as $refId => $refItem )
				{
					if( !isset( $listTypes[$refId] ) ) {
						$msg = sprintf( 'List type for text item with ID "%1$s" not available', $refId );
						throw new MShop_Catalog_Exception( $msg );
					}

					foreach( $listTypes[$refId] as $listType )
					{
						foreach( $prodIds[$id] as $productId )
						{
							$this->_saveText(
								$stmt, $productId, $siteid, $refId, $refItem->getLanguageId(), $listType,
								$refItem->getType(), 'attribute', $refItem->getContent(), $date, $editor
							);
						}
					}
				}

				$names = $item->getRefItems( 'text', 'name' );

				if( empty( $names ) )
				{
					$this->_saveText(
						$stmt, $prodIds[$id], $siteid, null, $locale->getLanguageId(), 'default',
						'name', 'attribute', $item->getLabel(), $date, $editor
					);
				}
			}

			$dbm->release( $conn, $dbname );
		}
		catch( Exception $e )
		{
			$dbm->release( $conn, $dbname );
			throw $e;
		}
	}
330248
public function getConfigAttributes( \Aimeos\MShop\Service\Item\Iface $item )
	{
		$manager = \Aimeos\MShop::create( $this->getContext(), 'service' );

		try {
			return $manager->getProvider( $item, $item->getType() )->getConfigBE();
		} catch( \Aimeos\MShop\Exception $e ) {
			return [];
		}
	}
104749
protected function fromArray( \Aimeos\MShop\Product\Item\Iface $item, array $data )
	{
		$manager = \Aimeos\MShop::create( $this->getContext(), 'catalog/lists' );
		$listIds = (array) $this->getValue( $data, 'catalog.lists.id', [] );
		$listItems = $map = $this->getListItems( $item->getId() );


		foreach( $listIds as $idx => $listid )
		{
			if( isset( $map[$listid] ) ) {
				unset( $map[$listid] );
			}
		}

		$manager->deleteItems( array_keys( $map ) );


		foreach( $listIds as $idx => $listid )
		{
			if( isset( $listItems[$listid] ) ) {
				$litem = $listItems[$listid];
			} else {
				$litem = $manager->createItem();
			}

			$litem->setDomain( 'product' );
			$litem->setRefId( $item->getId() );
			$litem->setParentId( $this->getValue( $data, 'catalog.id/' . $idx ) );
			$litem->setType( $this->getValue( $data, 'catalog.lists.type/' . $idx ) );

			$manager->saveItem( $litem, false );
		}
	}
22903
protected function doInsert(array &$a, array $options = array())
    {
        // If there is no file, perform a basic insertion
        if ( ! isset($a['file'])) {
            parent::doInsert($a, $options);
            return;
        }

        /* If the file is dirty (i.e. it must be persisted), delegate to the
         * storeFile() method. Otherwise, perform a basic insertion.
         */
        $file = $a['file']; // instanceof GridFSFile
        unset($a['file']);

        if ($file->isDirty()) {
            $this->storeFile($file, $a, $options);
        } else {
            parent::doInsert($a, $options);
        }

        $a['file'] = $file;
        return $a;
    }
250854
protected function execute( \Aimeos\MShop\Context\Item\Iface $context, array $customers )
	{
		$prodIds = $custIds = [];
		$listItems = $this->getListItems( $context, array_keys( $customers ) );
		$listManager = \Aimeos\MShop::create( $context, 'customer/lists' );

		foreach( $listItems as $id => $listItem )
		{
			$refId = $listItem->getRefId();
			$custIds[ $listItem->getParentId() ][$id] = $refId;
			$prodIds[$refId] = $refId;
		}

		$date = date( 'Y-m-d H:i:s' );
		$products = $this->getProducts( $context, $prodIds, 'default' );

		foreach( $custIds as $custId => $list )
		{
			$custListItems = $listIds = [];

			foreach( $list as $listId => $prodId )
			{
				$listItem = $listItems[$listId];

				if( $listItem->getDateEnd() < $date ) {
					$listIds[] = $listId;
				}

				$custListItems[$listId] = $listItems[$listId];
			}

			try
			{
				$custProducts = $this->getProductList( $products, $custListItems );

				if( !empty( $custProducts ) )
				{
					$addr = $customers[$custId]->getPaymentAddress();
					$this->sendMail( $context, $addr, $custProducts );

					$str = sprintf( 'Sent product notification e-mail to "%1$s"', $addr->getEmail() );
					$context->getLogger()->log( $str, \Aimeos\MW\Logger\Base::DEBUG );

					$listIds += array_keys( $custProducts );
				}
			}
			catch( \Exception $e )
			{
				$str = 'Error while trying to send product notification e-mail for customer ID "%1$s": %2$s';
				$context->getLogger()->log( sprintf( $str, $custId, $e->getMessage() ) );
			}

			$listManager->deleteItems( $listIds );
		}
	}
912532
public function set( \Aimeos\MShop\Common\Item\Iface $item )
	{
		$code = $item->getCode();

		if( !isset( $this->attributes[$code] ) || !is_array( $this->attributes[$code] ) ) {
			$this->attributes[$code] = [];
		}

		$this->attributes[$code][$item->getType()] = $item;
	}
527964
protected function fromArray( \Aimeos\MShop\Product\Item\Iface $item, array $data )
	{
		$manager = \Aimeos\MShop::create( $this->getContext(), 'stock' );

		$search = $manager->createSearch();
		$search->setConditions( $search->compare( '==', 'stock.productcode', $item->getCode() ) );
		$stockItems = $manager->searchitems( $search );

		$list = (array) $this->getValue( $data, 'stock.id', [] );

		foreach( $list as $idx => $id )
		{
			$type = $this->getValue( $data, 'stock.type/' . $idx );

			if( isset( $stockItems[$id] ) && $stockItems[$id]->getType() == $type )
			{
				$stockItem = $stockItems[$id];
				unset( $stockItems[$id] );
			}
			else
			{
				$stockItem = $manager->createItem()->setType( $type );
			}

			$stockItem->setProductCode( $item->getCode() );
			$stockItem->setStocklevel( $this->getValue( $data, 'stock.stocklevel/' . $idx ) );
			$stockItem->setDateBack( $this->getValue( $data, 'stock.dateback/' . $idx ) );

			$manager->saveItem( $stockItem, false );
		}

		$manager->deleteItems( array_keys( $stockItems ) );
	}
402974
protected function fromArray( \Aimeos\MShop\Attribute\Item\Iface $item, array $data )
	{
		$manager = \Aimeos\MShop::create( $this->getContext(), 'attribute/property' );

		$propItems = $item->getPropertyItems( null, false );

		foreach( $data as $entry )
		{
			if( isset( $propItems[$entry['attribute.property.id']] ) )
			{
				$propItem = $propItems[$entry['attribute.property.id']];
				unset( $propItems[$entry['attribute.property.id']] );
			}
			else
			{
				$propItem = $manager->createItem();
			}

			$propItem->fromArray( $entry, true );
			$item->addPropertyItem( $propItem );
		}

		$item->deletePropertyItems( $propItems );
	}
171666
protected function createNodeArray( \Aimeos\MShop\Catalog\Item\Iface $node )
	{
		$result = $node->toArray( true );

		foreach( $node->getChildren() as $child ) {
			$result['children'][] = $this->createNodeArray( $child );
		}

		return (object) $result;
	}
109159
public function add(array $item)
    {
        $item = array_merge([
            'id'       => null,
            'sku'      => null,
            'quantity' => 1,
            'price'    => 0,
            'discount' => 0,
            'name'     => null,
            'options'  => [],
        ], $item);

        // set sku
        $sku = empty($item[ 'sku' ]) ? $item[ 'id' ] : $item[ 'sku' ];

        // set sub-total
        $item[ 'subTotal' ][ 'price' ] = $item[ 'price' ] * $item[ 'quantity' ];
        $item[ 'subTotal' ][ 'discount' ] = 0;

        if (is_numeric($item[ 'discount' ])) {
            $item[ 'subTotal' ][ 'discount' ] = $item[ 'subTotal' ][ 'price' ] - $item[ 'discount' ];
        } elseif (is_string($item[ 'discount' ]) && strpos($item[ 'discount' ], '+') !== false) {
            $discounts = explode('+', $item[ 'discount' ]);
            if (count($discounts)) {
                $item[ 'subTotal' ][ 'discount' ] = $item[ 'subTotal' ][ 'price' ] * (intval(reset($discounts)) / 100);
                foreach (array_slice($discounts, 1) as $discount) {
                    $item[ 'subTotal' ][ 'discount' ] += $item[ 'subTotal' ][ 'discount' ] * (intval($discount) / 100);
                }
            }
        } elseif (is_string($item[ 'discount' ]) && strpos($item[ 'discount' ], '%') !== false) {
            $item[ 'subTotal' ][ 'discount' ] = $item[ 'subTotal' ][ 'price' ] * (intval($item[ 'discount' ]) / 100);
        }

        $item[ 'subTotal' ][ 'weight' ] = $item[ 'weight' ] * $item[ 'quantity' ];

        $this->storage[ $sku ] = $item;
    }