/**
  * Save the image assignment to the database
  *
  * @param Bundle $bundle     The bundle the image is assigned to
  * @param bool $delete       If set to true, existing images will be deleted from the database. Defaults to true.
  */
 public function save(Bundle $bundle, $delete = true)
 {
     if ($delete) {
         $this->_query->run("\n\t\t\t\tDELETE FROM\n\t\t\t\t\tdiscount_bundle_image\n\t\t\t\tWHERE\n\t\t\t\t\tbundle_id = :id?i\n\t\t\t", ['id' => $bundle->getID()]);
     }
     if ($bundle->getImage()) {
         $this->_query->run("\n\t\t\t\tINSERT INTO\n\t\t\t\t\tdiscount_bundle_image\n\t\t\t\t\t(\n\t\t\t\t\t\tbundle_id,\n\t\t\t\t\t\tfile_id\n\t\t\t\t\t)\n\t\t\t\tVALUES\n\t\t\t\t\t(\n\t\t\t\t\t\t:bundleID?i,\n\t\t\t\t\t\t:fileID?i\n\t\t\t\t\t)\n\t\t\t", ['bundleID' => $bundle->getID(), 'fileID' => $bundle->getImage()->id]);
     }
 }
 /**
  * Method for returning two arrays with matching keys.
  *
  * The first array is the expected counts array - a set of key value pairs of product row IDs and their quantity
  * value.
  *
  * The second array is the current counts array - a list of key value pairs of product row IDs and zeros, intended
  * to be incremented as the items in an order are counted against a bundle.
  *
  * @param Bundle\Bundle $bundle
  *
  * @return array         Returns array with the expected counts array as the first value and the current counts
  *                       array as the second value
  */
 function getCounts(Bundle\Bundle $bundle)
 {
     $expectedCounts = [];
     $currentCounts = [];
     foreach ($bundle->getProductRows() as $row) {
         $expectedCounts[$row->getID()] = $row->getQuantity();
         $currentCounts[$row->getID()] = 0;
     }
     return [$expectedCounts, $currentCounts];
 }
 public function validateAllowsCodes(Bundle $bundle, Order\Order $order)
 {
     if (false === $bundle->allowsCodes()) {
         foreach ($order->discounts as $discount) {
             if ($discount->getType() === Discount\OrderDiscountFactory::TYPE) {
                 $this->_error('ms.discount.bundle.validation.codes', ['%name%' => $bundle->getName(), '%code%' => $discount->code]);
             }
         }
     }
 }
 /**
  * Create a discount order entity to apply to the
  *
  * @param Order\Order $order
  * @param Bundle $bundle
  *
  * @return Order\Entity\Discount\Discount
  */
 public function createOrderDiscount(Order\Order $order, Bundle $bundle)
 {
     $discount = new Order\Entity\Discount\Discount();
     $type = $bundle->allowsCodes() ? self::CODES_ALLOWED : self::NO_CODES;
     $discount->setType($type);
     $discount->order = $order;
     $discount->amount = $this->_calculateAmount($order, $bundle);
     $discount->name = $bundle->getName();
     $discount->description = 'Bundle ' . $bundle->getID() . ': ' . $bundle->getName();
     $discount->order = $order;
     return $discount;
 }
 /**
  * Save bundle to the database
  *
  * @param Bundle $bundle
  *
  * @return Bundle           Return Bundle with ID and authorship details updated.
  */
 public function save(Bundle $bundle)
 {
     if (!$bundle->getAuthorship()->createdAt()) {
         $bundle->getAuthorship()->create(new DateTimeImmutable(), $this->_user->id);
     }
     $result = $this->_query->run("\n\t\t\tINSERT INTO\n\t\t\t\tdiscount_bundle\n\t\t\t\t(\n\t\t\t\t\t`name`,\n\t\t\t\t\tallow_codes,\n\t\t\t\t\tstart,\n\t\t\t\t\t`end`,\n\t\t\t\t\tcreated_at,\n\t\t\t\t\tcreated_by\n\t\t\t\t)\n\t\t\tVALUES\n\t\t\t\t(\n\t\t\t\t\t:name?s,\n\t\t\t\t\t:allowsCodes?b,\n\t\t\t\t\t:start?dn,\n\t\t\t\t\t:end?dn,\n\t\t\t\t\t:createdAt?d,\n\t\t\t\t\t:createdBy?i\n\t\t\t\t)\n\t\t", ['name' => $bundle->getName(), 'allowsCodes' => $bundle->allowsCodes(), 'start' => $bundle->getStart(), 'end' => $bundle->getEnd(), 'createdAt' => new \DateTime(), 'createdBy' => $this->_user->id]);
     $bundle->setID($result->id());
     $this->_bundleProductCreate->save($bundle);
     $this->_bundlePriceCreate->save($bundle);
     $this->_bundleImageCreate->save($bundle);
     return $bundle;
 }
 /**
  * {@inheritDoc}
  */
 public function getPrices()
 {
     if (!parent::getPrices()) {
         $this->_loadPrices();
     }
     return parent::getPrices();
 }
    /**
     * Save bundle prices to the database.
     *
     * @param Bundle $bundle    The bundle the prices are assigned to
     * @param bool $delete      If set to true, will delete prices currently assigned to database. True by default.
     */
    public function save(Bundle $bundle, $delete = true)
    {
        if ($delete) {
            $this->_query->run("\n\t\t\t\tDELETE FROM\n\t\t\t\t\tdiscount_bundle_price\n\t\t\t\tWHERE\n\t\t\t\t\tbundle_id = :bundleID?i\n\t\t\t", ['bundleID' => $bundle->getID()]);
        }
        $statements = [];
        foreach ($bundle->getPrices() as $currency => $price) {
            $statement = '(
				:bundleID?i,
				:currency?s,
				:price?f
			)';
            $params = ['bundleID' => $bundle->getID(), 'currency' => $currency, 'price' => $price];
            $statements[] = $this->_queryParser->parse($statement, $params);
        }
        $statements = implode(',' . PHP_EOL, $statements);
        $this->_query->run("\n\t\t\t\tINSERT INTO\n\t\t\t\t\tdiscount_bundle_price\n\t\t\t\t\t(\n\t\t\t\t\t\tbundle_id,\n\t\t\t\t\t\tcurrency,\n\t\t\t\t\t\tprice\n\t\t\t\t\t)\n\t\t\t\tVALUES\n\t\t\t" . $statements);
    }
 /**
  * Save changes to the bundle to the database
  *
  * @param Bundle $bundle
  */
 public function save(Bundle $bundle)
 {
     $this->_transaction->add("\n\t\t\tUPDATE\n\t\t\t\tdiscount_bundle\n\t\t\tSET\n\t\t\t\t`name` = :name?s,\n\t\t\t\tallow_codes = :allowsCodes?b,\n\t\t\t\tstart = :start?dn,\n\t\t\t\t`end` = :end?dn,\n\t\t\t\tupdated_at = :updatedAt?d,\n\t\t\t\tupdated_by = :updatedBy?i\n\t\t\tWHERE\n\t\t\t\tbundle_id = :bundleID?i\n\t\t", ['name' => $bundle->getName(), 'allowsCodes' => $bundle->allowsCodes(), 'start' => $bundle->getStart(), 'end' => $bundle->getEnd(), 'updatedAt' => new \DateTime(), 'updatedBy' => $this->_user->id, 'bundleID' => $bundle->getID()]);
     $this->_productCreate->save($bundle);
     $this->_priceCreate->setTransaction($this->_transaction);
     $this->_priceCreate->save($bundle);
     $this->_imageCreate->setTransaction($this->_transaction);
     $this->_imageCreate->save($bundle);
     $this->_commitTransaction();
 }
 /**
  * Save product data assigned to a bundle to the database
  *
  * @param Bundle $bundle   The bundle the product rows are assigned to
  * @param bool $delete     If set to true, existing product rows for the bundle will be deleted. True by default.
  */
 public function save(Bundle $bundle, $delete = true)
 {
     if ($delete) {
         $this->_query->run("\n\t\t\t\tDELETE FROM\n\t\t\t\t\tdiscount_bundle_product_row\n\t\t\t\tWHERE\n\t\t\t\t\tbundle_id = :bundleID?i\n\t\t\t", ['bundleID' => $bundle->getID()]);
         $this->_query->run("\n\t\t\t\tDELETE FROM\n\t\t\t\t\tdiscount_bundle_product_option\n\t\t\t\tWHERE\n\t\t\t\t\tbundle_id = :bundleID?i\n\t\t\t", ['bundleID' => $bundle->getID()]);
     }
     foreach ($bundle->getProductRows() as $row) {
         $result = $this->_query->run("\n\t\t\t\tINSERT INTO\n\t\t\t\t\tdiscount_bundle_product_row\n\t\t\t\t\t(\n\t\t\t\t\t\tbundle_id,\n\t\t\t\t\t\tproduct_id,\n\t\t\t\t\t\tquantity\n\t\t\t\t\t)\n\t\t\t\tVALUES\n\t\t\t\t\t(\n\t\t\t\t\t\t:bundleID?i,\n\t\t\t\t\t\t:productID?i,\n\t\t\t\t\t\t:quantity?i\n\t\t\t\t\t)\n\t\t\t", ['bundleID' => $bundle->getID(), 'productID' => $row->getProductID(), 'quantity' => $row->getQuantity()]);
         $statements = [];
         if (count($row->getOptions()) > 0) {
             foreach ($row->getOptions() as $name => $value) {
                 $statement = "\n\t\t\t\t\t(\n\t\t\t\t\t\t:rowID?i,\n\t\t\t\t\t\t:bundleID?i,\n\t\t\t\t\t\t:name?s,\n\t\t\t\t\t\t:value?s\n\t\t\t\t\t)";
                 $params = ['rowID' => $result->id(), 'bundleID' => $bundle->getID(), 'name' => $name, 'value' => $value];
                 $statements[] = $this->_queryParser->parse($statement, $params);
             }
             $statements = implode(',' . PHP_EOL, $statements);
             $this->_query->run("\n\t\t\t\t\tINSERT INTO\n\t\t\t\t\t\tdiscount_bundle_product_option\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\tproduct_row_id,\n\t\t\t\t\t\t\tbundle_id,\n\t\t\t\t\t\t\toption_name,\n\t\t\t\t\t\t\toption_value\n\t\t\t\t\t\t)\n\t\t\t\t\tVALUES\n\t\t\t\t" . $statements);
         }
     }
 }
 /**
  * Load file with ID matching that submitted, and assign it to the bundle.
  *
  * @param Bundle $bundle
  * @param array $data
  * @throws Exception\BundleBuildException    Throws exception if no file exists with submitted file ID
  * @throws Exception\BundleBuildException    Throws exception if the file loaded is not an image
  */
 private function _addImage(Bundle $bundle, array $data)
 {
     if (!empty($data[Form\BundleForm::IMAGE])) {
         $id = $data[Form\BundleForm::IMAGE];
         $image = $this->_fileLoader->getByID($id);
         if (!$image) {
             throw new Exception\BundleBuildException('Could not load file with ID `' . $id . '`');
         }
         if (!$image instanceof File\File || $image->typeID !== File\Type::IMAGE) {
             throw new Exception\BundleBuildException('File with ID `' . $id . '` is not a valid image');
         }
         $bundle->setImage($image);
     }
 }
 private function _getProducts(Bundle\Bundle $bundle)
 {
     $productIDs = [];
     $products = [];
     foreach ($bundle->getProductRows() as $productRow) {
         $productIDs[] = $productRow->getProductID();
     }
     foreach ($this->get('product.loader')->getByID($productIDs) as $product) {
         $products[$product->id] = $product;
     }
     return $products;
 }
 /**
  * Mark a bundle as not deleted
  *
  * @param Bundle $bundle
  */
 public function restore(Bundle $bundle)
 {
     $this->_query->run("\n\t\t\tUPDATE\n\t\t\t\tdiscount_bundle\n\t\t\tSET\n\t\t\t\tdeleted_at = NULL,\n\t\t\t\tdeleted_by = NULL\n\t\t\tWHERE\n\t\t\t\tbundle_id = :id?i\n\t\t", ['id' => $bundle->getID()]);
 }