CalculateProductPopularity::run()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
rs 10
1
<?php
2
3
namespace SilverShop\Tasks;
4
5
use SilverShop\Page\Product;
6
use SilverStripe\Dev\BuildTask;
7
use SilverStripe\ORM\DB;
8
9
class CalculateProductPopularity extends BuildTask
10
{
11
    protected $title = 'Calculate Product Sales Popularity';
12
13
    protected $description = 'Count up total sales quantites for each product';
14
15
    private static $number_sold_calculation_type = 'SUM'; //SUM or COUNT
16
17
    public function run($request)
18
    {
19
        if ($request->getVar('via') == 'php') {
20
            $this->viaphp();
21
        } else {
22
            $this->viasql();
23
        }
24
        echo 'product sales counts updated';
25
    }
26
27
    /**
28
     * Update both live and stage tables, based on the algorithm:
29
     *    product popularity = sum(1/order_age) * sum(item_quantity)
30
     */
31
    public function viasql()
32
    {
33
        foreach (['_Live', ''] as $stage) {
34
            $sql = <<<SQL
35
UPDATE "SilverShop_Product$stage" SET "Popularity" = (
36
  SELECT
37
    SUM(1 / (DATEDIFF(NOW(),"SilverShop_Order"."Paid")+1)) * SUM("SilverShop_OrderItem"."Quantity")
38
    #  / DATEDIFF("SiteTree$stage"."Created",NOW())
39
    AS Popularity
40
  FROM "SiteTree$stage"
41
    INNER JOIN "SilverShop_Product_OrderItem" ON "SiteTree$stage"."ID" = "SilverShop_Product_OrderItem"."ProductID"
42
    INNER JOIN "SilverShop_OrderItem" ON "SilverShop_OrderItem"."ID" = "SilverShop_Product_OrderItem"."ID"
43
    INNER JOIN "SilverShop_OrderAttribute" ON "SilverShop_OrderItem"."ID" = "SilverShop_OrderAttribute"."ID"
44
    INNER JOIN "SilverShop_Order" ON "SilverShop_OrderAttribute"."OrderID" = "SilverShop_Order"."ID"
45
  WHERE "SiteTree$stage"."ID" = "SilverShop_Product$stage"."ID"
46
    AND "SilverShop_Order"."Paid" IS NOT NULL
47
  GROUP BY "SilverShop_Product$stage"."ID"
48
);
49
SQL;
50
            DB::query($sql);
51
        }
52
    }
53
54
    //legacy function  for working out popularity
55
    public function viaphp()
56
    {
57
        $ps = singleton(Product::class);
58
        $q = $ps->buildSQL('"SilverShop_Product"."AllowPurchase" = 1');
59
        $select = $q->select;
60
        $select['NewPopularity'] =
61
            self::config()->number_sold_calculation_type . '("SilverShop_OrderItem"."Quantity") AS "NewPopularity"';
62
        $q->select($select);
63
        $q->groupby('"Product"."ID"');
64
        $q->orderby('"NewPopularity" DESC');
65
        $q->leftJoin('SilverShop_Product_OrderItem', '"SilverShop_Product"."ID" = "SilverShop_Product_OrderItem"."ProductID"');
66
        $q->leftJoin('SilverShop_OrderItem', '"SilverShop_Product_OrderItem"."ID" = "SilverShop_OrderItem"."ID"');
67
        $records = $q->execute();
68
        $productssold = $ps->buildDataObjectSet($records, "DataObjectSet", $q, Product::class);
69
        //TODO: this could be done faster with an UPDATE query (SQLQuery doesn't support this yet @11/06/2010)
70
        foreach ($productssold as $product) {
71
            if ($product->NewPopularity != $product->Popularity) {
72
                $product->Popularity = $product->NewPopularity;
73
                $product->writeToStage('Stage');
74
                $product->publishSingle();
75
            }
76
        }
77
    }
78
}
79