Skip to content

Commit

Permalink
Add allow setting of extra data on factories instead of passing custo…
Browse files Browse the repository at this point in the history
…m data on methods
  • Loading branch information
mlewis-everley committed Oct 28, 2024
1 parent c7ffa65 commit f18725a
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 46 deletions.
96 changes: 72 additions & 24 deletions src/Factory/LineItemFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@
namespace SilverCommerce\OrdersAdmin\Factory;

use LogicException;
use SilverCommerce\OrdersAdmin\Interfaces\LineItemCustomisable;
use SilverStripe\ORM\SS_List;
use SilverStripe\Core\ClassInfo;
use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\ValidationException;
use SilverCommerce\TaxAdmin\Model\TaxRate;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Injector\Injectable;
use SilverCommerce\OrdersAdmin\Model\Estimate;
use SilverCommerce\OrdersAdmin\Model\LineItem;
use SilverCommerce\OrdersAdmin\Model\PriceModifier;
use SilverCommerce\OrdersAdmin\Interfaces\LineItemPricable;
use SilverCommerce\OrdersAdmin\Model\LineItemCustomisation;
use SilverCommerce\OrdersAdmin\Traits\ExtraData;

/**
* Factory that handles setting up line items based on submitted data
*/
class LineItemFactory
{
use Injectable, Configurable;
use Configurable, Injectable, ExtraData;

const ITEM_CLASS = LineItem::class;

Expand Down Expand Up @@ -130,9 +135,21 @@ class LineItemFactory
*/
protected $customisations = [];

protected function getPotentialPriceModifiers()
{
return ClassInfo::implementorsOf(LineItemPricable::class);
}

protected function getPotentialCustomisers()
{
return ClassInfo::implementorsOf(LineItemCustomisable::class);
}

/**
* Either find an existing line item (based on the submitted data),
* or return a new one.
* Either find an existing line item (based on the submitted
* data), or generate a new one.
*
* Also search for any potential
*
* @return self
*/
Expand All @@ -142,11 +159,27 @@ public function makeItem(): self

// Setup initial line item
$item = $class::create($this->getItemArray());
$data = $this->getExtraData();

// Setup Key
$item->Key = $this->generateKey();
$this->setItem($item);

$modifiers = $this->getPotentialPriceModifiers();
$customisers = $this->getPotentialCustomisers();

foreach ($modifiers as $modifier_class) {
/** @var LineItemPricable */
$pricable = Injector::inst()->get($modifier_class, true);
$pricable->modifyItemPrice($this, $data);
}

foreach ($customisers as $custom_class) {
/** @var LineItemCustomiser */
$customiser = Injector::inst()->get($custom_class, true);
$customiser->customiseLineItem($this, $data);
}

return $this;
}

Expand All @@ -163,7 +196,8 @@ public function makeItem(): self
public function customise(
string $name,
string $value,
array $additional_data = []
array $additional_data = [],
DataObject $related = null
): LineItemCustomisation {
$item = $this->getItem();

Expand All @@ -179,6 +213,10 @@ public function customise(
$customisation->Title = $name;
$customisation->Value = $value;

if (!empty($related)) {
$customisation->Related = $related;
}

$item
->Customisations()
->add($customisation);
Expand All @@ -196,16 +234,17 @@ public function customise(

$customisation->write();
$this->update();

return $customisation;
}

/**
* Generate a customisation and/or price
* modification for the current item
*
* @param string $name The name of this modification (eg: size)
* @param float $amount The amount to modify the price by (either positive or negative)
* @param int $customisation_id Optionally link this to a customisation
* @param string $name The name of this modification (eg: size)
* @param float $amount The amount to modify the price by (either positive or negative)
* @param DataObject $related Optionally link this relation to a @link DataObject
*
* @throws LogicException
*
Expand All @@ -214,38 +253,47 @@ public function customise(
public function modifyPrice(
string $name,
float $amount,
int $customisation_id = 0
DataObject $related = null
): PriceModifier {
$item = $this->getItem();
$modifier_class = self::PRICE_CLASS;
$modifier = null;

if (empty($item)) {
throw new LogicException('No LineItem available, did you use `makeItem`?');
}

$class = self::PRICE_CLASS;
if (!empty($related) && !$related instanceof LineItemPricable) {
throw new LogicException('Related objects for a LineItem modifier must implement LineItemPricable');
}

if (!empty($related)) {
/** @var PriceModifier */
$modifier = DataObject::get($modifier_class)
->filter([
'RelatedObjectID' => $related->ID,
'RelatedObjectClass' => $related->ClassName
])->first();
}

if (empty($modifier)) {
/** @var PriceModifier */
$modifier = $modifier_class::create();
}

/** @var PriceModifier */
$modifier = $class::create();
$modifier->Name = $name;
$modifier->ModifyPrice = $amount;

if (!empty($related)) {
$modifier->RelatedObject = $related;
}

$modifier->write();

$item
->PriceModifications()
->add($modifier);

if ($customisation_id > 0) {
$customisation = $item
->Customisations()
->byID($customisation_id);

if (empty($customisation)) {
throw new LogicException("Invalid customisation passed to modifier");
}

$modifier->CustomisationID = $customisation_id;
}

$modifier->write();
return $modifier;
}

Expand Down
25 changes: 3 additions & 22 deletions src/Factory/OrderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
use SilverCommerce\ContactAdmin\Model\Contact;
use SilverCommerce\OrdersAdmin\Model\Estimate;
use SilverCommerce\OrdersAdmin\Factory\LineItemFactory;
use SilverCommerce\OrdersAdmin\Traits\ExtraData;
use SilverStripe\Core\Config\Config;

class OrderFactory
{
use Injectable, Configurable;
use Injectable, Configurable, ExtraData;

/**
* The class this factory uses to create an estimate
Expand Down Expand Up @@ -275,36 +276,16 @@ public function addItem(
DataObject $product,
int $qty = 1,
bool $lock = false,
array $custom = [],
bool $deliver = true
) {
$factory = LineItemFactory::create()
->setProduct($product)
->setQuantity($qty)
->setLock($lock)
->setDeliverable($deliver)
->setExtraData($this->getExtraData())
->makeItem()
->write();

// Setup customisations
foreach ($custom as $customisation) {
if (!isset($customisation['Title']) || !isset($customisation['Value'])) {
throw new LogicException('Customisations require a Title AND a value');
}

$custom_item = $factory->customise(
$customisation['Title'],
$customisation['Value']
);

if (isset($customisation['BasePrice'])) {
$factory->modifyPrice(
$customisation['Title'] . ': ' .$customisation['Value'],
$customisation['BasePrice'],
$custom_item->ID
);
}
}

$this->addFromLineItemFactory($factory);

Expand Down
28 changes: 28 additions & 0 deletions src/Traits/ExtraData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace SilverCommerce\OrdersAdmin\Traits;

trait ExtraData
{
/**
* Array of optional extra data that can be passed to this factory.
* (and will be passed into @link LineItemFactory).
*
* The intention is to allow custom extensions to pass generic data
* that can be accessed further down the stack
*
* @var array
*/
protected $extra_data = [];

public function getExtraData(): array
{
return $this->extra_data;
}

public function setExtraData(array $data): self
{
$this->extra_data = $data;
return $this;
}
}

0 comments on commit f18725a

Please sign in to comment.