Adds the necessary headers and the download content to the reponse object

@param \Aimeos\MShop\Order\Item\Base\Product\Attribute\Iface $item Order product attribute item with file reference
189099
protected function addDownload( \Aimeos\MShop\Order\Item\Base\Product\Attribute\Iface $item )
	{
		$fs = $this->getContext()->getFilesystemManager()->get( 'fs-secure' );
		$response = $this->getView()->response();
		$value = (string) $item->getValue();

		if( $fs->has( $value ) )
		{
			$name = $item->getName();

			if( pathinfo( $name, PATHINFO_EXTENSION ) == null
					&& ( $ext = pathinfo( $value, PATHINFO_EXTENSION ) ) != null
			) {
				$name .= '.' . $ext;
			}

			$response->withHeader( 'Content-Description', 'File Transfer' );
			$response->withHeader( 'Content-Type', 'application/octet-stream' );
			$response->withHeader( 'Content-Disposition', 'attachment; filename="' . $name . '"' );
			$response->withHeader( 'Content-Length', (string) $fs->size( $value ) );
			$response->withHeader( 'Cache-Control', 'must-revalidate' );
			$response->withHeader( 'Pragma', 'private' );
			$response->withHeader( 'Expires', '0' );

			$response->withBody( $response->createStream( $fs->reads( $value ) ) );
		}
		elseif( filter_var( $value, FILTER_VALIDATE_URL ) !== false )
		{
			$response->withHeader( 'Location', $value );
			$response->withStatus( 303 );
		}
		else
		{
			$response->withStatus( 404 );
		}
	}
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;
	}
496747
protected function addGroups( \Aimeos\MShop\Context\Item\Iface $context, \Aimeos\MShop\Customer\Item\Iface $user )
	{
		\Illuminate\Foundation\Auth\User::findOrFail( $user->getId() )
			->forceFill( ['superuser' => ( $this->option( 'super' ) ? 1 : 0 )] )
			->save();

		if( $this->option( 'admin' ) ) {
			$this->addGroup( $context, $user, 'admin' );
		}

		if( $this->option( 'editor' ) ) {
			$this->addGroup( $context, $user, 'editor' );
		}

		if( $this->option( 'api' ) ) {
			$this->addGroup( $context, $user, 'api' );
		}
	}
22436
protected static function addSession( \Aimeos\MShop\Context\Item\Iface $context )
	{
		if( isset( $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_session'] )
			&& is_callable( ( $fcn = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_session'] ) )
		) {
			return $fcn( $context );
		}

		if( isset( $GLOBALS['TSFE']->fe_user ) ) {
			$session = new \Aimeos\MW\Session\Typo3( $GLOBALS['TSFE']->fe_user );
		} elseif( isset( $GLOBALS['BE_USER'] ) ) {
			$session = new \Aimeos\MW\Session\Typo3( $GLOBALS['BE_USER'] );
		} else {
			$session = new \Aimeos\MW\Session\None();
		}

		return $context->setSession( $session );
	}
485423
protected function getProducts( \Aimeos\MShop\Context\Item\Iface $context, array $prodIds, $stockType )
	{
		$productCodes = $stockMap = [];
		$productItems = $this->getProductItems( $context, $prodIds );

		foreach( $productItems as $productItem ) {
			$productCodes[] = $productItem->getCode();
		}

		foreach( $this->getStockItems( $context, $productCodes, $stockType ) as $stockItem ) {
			$stockMap[ $stockItem->getProductCode() ] = true;
		}

		foreach( $productItems as $productId => $productItem )
		{
			if( !isset( $stockMap[ $productItem->getCode() ] ) ) {
				unset( $productItems[$productId] );
			}
		}

		return $productItems;
	}
374685
public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
	{
		self::checkClass( \Aimeos\MShop\Customer\Item\Group\Iface::class, $item );

		if( !$item->isModified() ) {
			return $item;
		}

		$context = $this->getContext();

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

		try
		{
			$id = $item->getId();

			if( $id === null )
			{
				/** mshop/customer/manager/group/typo3/insert/mysql
				 * Inserts a new customer group record into the database table
				 *
				 * @see mshop/customer/manager/group/typo3/insert/ansi
				 */

				/** mshop/customer/manager/group/typo3/insert/ansi
				 * Inserts a new customer group record into the database table
				 *
				 * Items with no ID yet (i.e. the ID is NULL) will be created in
				 * the database and the newly created ID retrieved afterwards
				 * using the "newid" SQL statement.
				 *
				 * The SQL statement must be a string suitable for being used as
				 * prepared statement. It must include question marks for binding
				 * the values from the customer group item to the statement before
				 * they are sent to the database server. The number of question
				 * marks must be the same as the number of columns listed in the
				 * INSERT statement. The order of the columns must correspond to
				 * the order in the saveItems() method, so the correct values are
				 * bound to the columns.
				 *
				 * The SQL statement should conform to the ANSI standard to be
				 * compatible with most relational database systems. This also
				 * includes using double quotes for table and column names.
				 *
				 * @param string SQL statement for inserting records
				 * @since 2015.08
				 * @category Developer
				 * @see mshop/customer/manager/group/typo3/update/ansi
				 * @see mshop/customer/manager/group/typo3/newid/ansi
				 * @see mshop/customer/manager/group/typo3/delete/ansi
				 * @see mshop/customer/manager/group/typo3/search/ansi
				 * @see mshop/customer/manager/group/typo3/count/ansi
				 */
				$path = 'mshop/customer/manager/group/typo3/insert';
			}
			else
			{
				/** mshop/customer/manager/group/typo3/update/mysql
				 * Updates an existing customer group record in the database
				 *
				 * @see mshop/customer/manager/group/typo3/update/ansi
				 */

				/** mshop/customer/manager/group/typo3/update/ansi
				 * Updates an existing customer group record in the database
				 *
				 * Items which already have an ID (i.e. the ID is not NULL) will
				 * be updated in the database.
				 *
				 * The SQL statement must be a string suitable for being used as
				 * prepared statement. It must include question marks for binding
				 * the values from the customer group item to the statement before
				 * they are sent to the database server. The order of the columns
				 * must correspond to the order in the saveItems() method, so the
				 * correct values are bound to the columns.
				 *
				 * The SQL statement should conform to the ANSI standard to be
				 * compatible with most relational database systems. This also
				 * includes using double quotes for table and column names.
				 *
				 * @param string SQL statement for updating records
				 * @since 2015.08
				 * @category Developer
				 * @see mshop/customer/manager/group/typo3/insert/ansi
				 * @see mshop/customer/manager/group/typo3/newid/ansi
				 * @see mshop/customer/manager/group/typo3/delete/ansi
				 * @see mshop/customer/manager/group/typo3/search/ansi
				 * @see mshop/customer/manager/group/typo3/count/ansi
				 */
				$path = 'mshop/customer/manager/group/typo3/update';
			}

			$stmt = $this->getCachedStatement( $conn, $path );

			$stmt->bind( 1, $this->pid, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
			$stmt->bind( 2, $item->getCode() );
			$stmt->bind( 3, $item->getLabel() );
			$stmt->bind( 4, time(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); // mtime

			if( $id !== null ) {
				$stmt->bind( 5, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
				$item->setId( $id );
			} else {
				$stmt->bind( 5, time() ); // ctime
			}

			$stmt->execute()->finish();

			if( $id === null && $fetch === true )
			{
				/** mshop/customer/manager/group/typo3/newid/mysql
				 * Retrieves the ID generated by the database when inserting a new record
				 *
				 * @see mshop/customer/manager/group/typo3/newid/ansi
				 */

				/** mshop/customer/manager/group/typo3/newid/ansi
				 * Retrieves the ID generated by the database when inserting a new record
				 *
				 * As soon as a new record is inserted into the database table,
				 * the database server generates a new and unique identifier for
				 * that record. This ID can be used for retrieving, updating and
				 * deleting that specific record from the table again.
				 *
				 * For MySQL:
				 *  SELECT LAST_INSERT_ID()
				 * For PostgreSQL:
				 *  SELECT currval('seq_mcus_id')
				 * For SQL Server:
				 *  SELECT SCOPE_IDENTITY()
				 * For Oracle:
				 *  SELECT "seq_mcus_id".CURRVAL FROM DUAL
				 *
				 * There's no way to retrive the new ID by a SQL statements that
				 * fits for most database servers as they implement their own
				 * specific way.
				 *
				 * @param string SQL statement for retrieving the last inserted record ID
				 * @since 2015.08
				 * @category Developer
				 * @see mshop/customer/manager/group/typo3/insert/ansi
				 * @see mshop/customer/manager/group/typo3/update/ansi
				 * @see mshop/customer/manager/group/typo3/delete/ansi
				 * @see mshop/customer/manager/group/typo3/search/ansi
				 * @see mshop/customer/manager/group/typo3/count/ansi
				 */
				$path = 'mshop/customer/manager/group/typo3/newid';
				$item->setId( $this->newId( $conn, $path ) );
			}

			$dbm->release( $conn, $dbname );
		}
		catch( \Exception $e )
		{
			$dbm->release( $conn, $dbname );
			throw $e;
		}

		return $item;
	}
452349
protected function addDatabaseManager( \Aimeos\MShop\Context\Item\Iface $context )
	{
		$dbm = new \Aimeos\MW\DB\Manager\DBAL( $context->getConfig() );

		return $context->setDatabaseManager( $dbm );
	}
945293
protected function addAccess( \Aimeos\MW\View\Iface $view, \Aimeos\MShop\Context\Item\Iface $context )
	{
		if( $this->config->get( 'shop.accessControl', true ) === false
			|| ( ( $user = \Illuminate\Support\Facades\Auth::user() ) !== null && $user->superuser )
		) {
			$helper = new \Aimeos\MW\View\Helper\Access\All( $view );
		}
		else
		{
			$support = $this->support;

			$fcn = function() use ( $support, $context ) {
				return $support->getGroups( $context );
			};

			$helper = new \Aimeos\MW\View\Helper\Access\Standard( $view, $fcn );
		}

		$view->addHelper( 'access', $helper );

		return $view;
	}
878573
protected function fromArray( \Aimeos\MShop\Customer\Item\Iface $item, array $data )
	{
		$context = $this->getContext();
		$listIds = $this->getValue( $data, 'customer.lists.id', [] );

		$listManager = \Aimeos\MShop::create( $context, 'customer/lists' );

		$search = $listManager->createSearch()->setSlice( 0, count( $listIds ) );
		$search->setConditions( $search->compare( '==', 'customer.lists.id', $listIds ) );

		$listItems = $listManager->searchItems( $search );


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

			$litem->setParentId( $item->getId() );
			$litem->setDomain( 'product' );

			if( isset( $data['customer.lists.refid'][$idx] ) ) {
				$litem->setRefId( $this->getValue( $data, 'customer.lists.refid/' . $idx ) );
			}

			if( isset( $data['customer.lists.status'][$idx] ) ) {
				$litem->setStatus( $this->getValue( $data, 'customer.lists.status/' . $idx ) );
			}

			if( isset( $data['customer.lists.type'][$idx] ) ) {
				$litem->setType( $this->getValue( $data, 'customer.lists.type/' . $idx ) );
			}

			if( isset( $data['customer.lists.position'][$idx] ) ) {
				$litem->setPosition( $this->getValue( $data, 'customer.lists.position/' . $idx ) );
			}

			if( isset( $data['customer.lists.datestart'][$idx] ) ) {
				$litem->setDateStart( $this->getValue( $data, 'customer.lists.datestart/' . $idx ) );
			}

			if( isset( $data['customer.lists.dateend'][$idx] ) ) {
				$litem->setDateEnd( $this->getValue( $data, 'customer.lists.dateend/' . $idx ) );
			}

			if( isset( $data['customer.lists.config'][$idx] )
				&& ( $conf = json_decode( $this->getValue( $data, 'customer.lists.config/' . $idx ), true ) ) !== null
			) {
				$litem->setConfig( $conf );
			}

			if( $litem->getId() === null && isset( $data['config'][$idx]['key'] ) )
			{
				$conf = [];

				foreach( (array) $data['config'][$idx]['key'] as $pos => $key )
				{
					if( trim( $key ) !== '' && isset( $data['config'][$idx]['val'][$pos] ) ) {
						$conf[$key] = $data['config'][$idx]['val'][$pos];
					}
				}

				$litem->setConfig( $conf );
			}

			$listManager->saveItem( $litem, false );
		}
	}
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 );
		}
	}
1374913
protected function addViewData( \Aimeos\MW\View\Iface $view )
	{
		$manager = \Aimeos\MShop::create( $this->getContext(), 'media/property/type' );

		$search = $manager->createSearch( true )->setSlice( 0, 10000 );
		$search->setConditions( $search->compare( '==', 'media.property.type.domain', 'service' ) );
		$search->setSortations( [$search->sort( '+', 'media.property.type.position')] );

		$view->propertyTypes = $this->map( $manager->searchItems( $search ) );

		return $view;
	}
455417
public function addItem(GridItem $item, $order = null)
    {
        if (empty($this->getItem($item->getUuid()))) {
            $rowItem = new GridRowItem();
            $rowItem->setOrder(isset($order) || 0 === $order ? $order : $this->rowItems->count());
            $rowItem->setRow($this);
            $rowItem->setItem($item);

            $this->rowItems->add($rowItem);
        }
    }
1066471
protected function addFilesystemManager( \Aimeos\MShop\Context\Item\Iface $context )
	{
		$fs = new \Aimeos\MW\Filesystem\Manager\Standard( $context->getConfig() );

		return $context->setFilesystemManager( $fs );
	}
535920
protected static function addLogger( \Aimeos\MShop\Context\Item\Iface $context )
	{
		if( isset( $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_logger'] )
			&& is_callable( ( $fcn = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_logger'] ) )
		) {
			return $fcn( $context );
		}

		return $context->setLogger( \Aimeos\MAdmin::create( $context, 'log' ) );
	}
194883
protected function toArray( \Aimeos\MShop\Customer\Item\Iface $item, $copy = false )
	{
		$data = $item->toArray( true );

		if( $copy === true )
		{
			$data['customer.siteid'] = $this->getContext()->getLocale()->getSiteId();
			$data['customer.email'] = '';
			$data['customer.id'] = '';
		}

		return $data;
	}
866172
protected static function addCache( \Aimeos\MShop\Context\Item\Iface $context )
	{
		if( isset( $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_cache'] )
			&& is_callable( ( $fcn = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['aimeos']['aimeos_context_cache'] ) )
		) {
			return $fcn( $context );
		}

		$cacheName = \Aimeos\Aimeos\Base::getExtConfig( 'cacheName', 'Typo3' );
		if ( isset( $GLOBALS['TSFE'] ) && $GLOBALS['TSFE']->headerNoCache() ) {
    			$cacheName = 'None';
		}

		switch( $cacheName )
		{
			case 'None':
				$context->getConfig()->set( 'client/html/basket/cache/enable', false );
				$cache = \Aimeos\MW\Cache\Factory::create( 'None', array(), null );
				break;

			case 'Typo3':
				$manager = GeneralUtility::makeInstance( \TYPO3\CMS\Core\Cache\CacheManager::class );
				$cache = new \Aimeos\MAdmin\Cache\Proxy\Typo3( $context, $manager->getCache( 'aimeos' ) );
				break;

			default:
				$cache = new \Aimeos\MAdmin\Cache\Proxy\Standard( $context );
		}

		return $context->setCache( $cache );
	}
717780
protected function fromArray( \Aimeos\MShop\Supplier\Item\Iface $item, array $data )
	{
		$context = $this->getContext();

		$mediaManager = \Aimeos\MShop::create( $context, 'media' );
		$listManager = \Aimeos\MShop::create( $context, 'supplier/lists' );
		$cntl = \Aimeos\Controller\Common\Media\Factory::create( $context );

		$listItems = $item->getListItems( 'media', null, null, false );
		$files = (array) $this->getView()->request()->getUploadedFiles();

		foreach( $data as $idx => $entry )
		{
			if( ( $listItem = $item->getListItem( 'media', $entry['supplier.lists.type'], $entry['media.id'], false ) ) === null ) {
				$listItem = $listManager->createItem();
			}

			if( ( $refItem = $listItem->getRefItem() ) === null ) {
				$refItem = $mediaManager->createItem();
			}

			$refItem->fromArray( $entry, true );

			if( ( $file = $this->getValue( $files, 'media/' . $idx . '/file' ) ) !== null && $file->getError() !== UPLOAD_ERR_NO_FILE )
			{
				$refItem->getId() ?: $refItem->setUrl( '' )->setPreview( '' ); // keep copied media
				$cntl->add( $refItem, $file );
			}

			$conf = [];

			foreach( (array) $this->getValue( $entry, 'config/key' ) as $num => $key )
			{
				if( trim( $key ) !== '' && ( $val = $this->getValue( $entry, 'config/val/' . $num ) ) !== null ) {
					$conf[$key] = trim( $val );
				}
			}

			$listItem->fromArray( $entry, true );
			$listItem->setPosition( $idx );
			$listItem->setConfig( $conf );

			$item->addListItem( 'media', $listItem, $refItem );

			unset( $listItems[$listItem->getId()] );
		}

		return $this->deleteMediaItems( $item, $listItems );
	}