mardi 22 juin 2021

How to refactor two similar methods and create correct readeable methods?

I have two similar methods in my controller:

First method:

public function parseDataLayerEvent()
{
    $events = $this->pixel_log->data['dataLayer'];

    if (!is_array($events)) {
        throw new \Exception('dataLayer is not an array');
    }
    foreach ($events as $event) {
        if (!isset($event['event'])) {
            continue;
        }
        if (!isset($event['ecommerce'])) {
            continue;
        }
        if (!isset($event['ecommerce']['purchase'])) {
            continue;
        }
        $purchase = $event['ecommerce']['purchase'];

        $validator = Validator::make($purchase, [
            'products.*.id' => 'required|string',
            'products.*.name' => 'required|string',
            'products.*.price' => 'required|numeric',
            'products.*.variant' => 'nullable|string',
            'products.*.category' => 'nullable|string',
            'products.*.quantity' => 'nullable|numeric|min:1',
            'actionField.id' => 'required|string',
            'actionField.action' => 'nullable|string|in:purchase',
            'actionField.revenue' => 'required|numeric',
        ]);

        if ($validator->fails()) {
            logger()->debug('Order validation failure');
            throw new ValidationException($validator);
        }

        $order_id = $purchase['actionField']['id'];
        $order = Order::query()
            ->where('pp_id', '=', $this->pixel_log->pp_id)
            ->where('order_id', '=', $order_id)
            ->first();

        if (!$order) {
            logger()->debug('Order №' . $order_id . ' does not exist, creating...');
            $order = new Order();
            $order->pp_id = $this->pixel_log->pp_id;
            $order->order_id = $order_id;
            $order->status = 'new';
        } else {
            logger()->debug('Order №' . $order_id . ' exist, updating');
        }
        $order->pixel_id = $this->pixel_log->id;
        $order->datetime = $this->pixel_log->created_at;
        $order->partner_id = $this->link->partner_id;
        $order->link_id = $this->link->id;
        $order->click_id = $this->pixel_log->data['click_id'] ?? null;
        $order->web_id = $this->pixel_log->data['utm_term'] ?? null;
        $order->offer_id = $this->link->offer_id;
        $order->client_id = $this->client->id;
        $order->gross_amount = 0;
        foreach ($purchase['products'] as $product_data) {
            $order->gross_amount += $product_data['price'] * ($product_data['quantity'] ?? 1);
        }
        
        $total_products = count($purchase['products']);
        $order->cnt_products = $total_products;
        $order->save();

        logger()->debug('Products found: ' . $total_products);
        foreach ($purchase['products'] as $product_data) {
            $product_id = $product_data['id'];
            $product = OrdersProduct::query()
                    ->where('pp_id', '=', $this->pixel_log->pp_id)
                    ->where('order_id', '=', $order->order_id)
                    ->where('product_id', '=', $product_id)
                    ->first() ?? new OrdersProduct();

            // if ($product->wasRecentlyCreated === false) {
            //     if (!is_null($product->reestr_id)) {
            //         return;
            //     }
            //     if ($product->status !== 'new') {
            //         return;
            //     }
            // }

            $product->pp_id = $this->pixel_log->pp_id;
            $product->order_id = $order->order_id;
            $product->parent_id = Order::query()
                ->where('pp_id', '=', $this->pixel_log->pp_id)
                ->where('order_id', '=', $order_id)
                ->first()->id;
            $product->datetime = $order->datetime;
            $product->partner_id = $order->partner_id;
            $product->offer_id = $order->offer_id;
            $product->link_id = $order->link_id;
            $product->product_id = $product_id;
            $product->product_name = trim(($product_data['name'] ?? '') . ' ' . ($product_data['variant'] ?? ''));
            $product->category = $product_data['category'] ?? null;
            $product->price = $product_data['price'];
            $product->quantity = $product_data['quantity'] ?? 1;
            $product->total = $product->price * $product->quantity;
            $product->web_id = $order->web_id;
            $product->click_id = $order->click_id;
            $product->pixel_id = $order->pixel_id;
            $product->amount = 0;
            $product->amount_advert = 0;
            $product->fee_advert = 0;
            $product->save();
            logger()->debug('Saved product: ' . $product->product_name);
        }
        $this->pixel_log->is_order = true;
        return true;
    }
}

Second method:

public function parseCheckoutDataLayerEvent()
{
    $events = $this->pixel_log->data['dataLayer'];

    if (!is_array($events)) {
        throw new \Exception('dataLayer is not an array');
    }
    foreach ($events as $event) {
        if (!isset($event['event'])) {
            continue;
        }
        if (!isset($event['ecommerce'])) {
            continue;
        }
        if (!isset($event['ecommerce']['checkout'])) {
            continue;
        }

        $purchase = $event['ecommerce']['checkout'];
        $validator = Validator::make($purchase, [
            'products.*.id' => 'required|string',
            'products.*.name' => 'required|string',
            'products.*.price' => 'required|numeric',
            'products.*.variant' => 'nullable|string',
            'products.*.category' => 'nullable|string',
            'products.*.quantity' => 'nullable|numeric|min:1',
        ]);

        if ($validator->fails()) {
            logger()->debug('Ошибка валидации заказа');
            throw new ValidationException($validator);
        }

        $order_id = $this->pixel_log->data['ed']['order_id'];
        $order = Order::query()
            ->where('pp_id', '=', $this->pixel_log->pp_id)
            ->where('order_id', '=', $order_id)
            ->first();

        if (!$order) {
            logger()->debug('Order №' . $order_id . ' does not exist, creating...');
            $order = new Order();
            $order->pp_id = $this->pixel_log->pp_id;
            $order->order_id = $order_id;
            $order->status = 'new';
        } else {
            logger()->debug('Order №' . $order_id . ' exist, updating');
        }
        $order->pixel_id = $this->pixel_log->id;
        $order->datetime = $this->pixel_log->created_at;
        $order->partner_id = $this->link->partner_id;
        $order->link_id = $this->link->id;
        $order->click_id = $this->pixel_log->data['click_id'] ?? null;
        $order->web_id = $this->pixel_log->data['utm_term'] ?? null;
        $order->offer_id = $this->link->offer_id;
        $order->client_id = $this->client->id;
        $order->gross_amount = 0;
        foreach ($purchase['products'] as $product_data) {
            $order->gross_amount += $product_data['price'] * ($product_data['quantity'] ?? 1);
        }
        // $order->gross_amount = $purchase['actionField']['revenue'] - ($purchase['actionField']['shipping'] ?? 0);
        $order->cnt_products = count($purchase['products']);
        $order->save();

        logger()->debug('Products found: ' . count($purchase['products']));
        foreach ($purchase['products'] as $product_data) {
            $product_id = $product_data['id'];
            $product = OrdersProduct::query()
                    ->where('pp_id', '=', $this->pixel_log->pp_id)
                    ->where('order_id', '=', $order->order_id)
                    ->where('product_id', '=', $product_id)
                    ->first() ?? new OrdersProduct();

            // if ($product->wasRecentlyCreated === false) {
            //     if (!is_null($product->reestr_id)) {
            //         return;
            //     }
            //     if ($product->status !== 'new') {
            //         return;
            //     }
            // }

            $product->pp_id = $this->pixel_log->pp_id;
            $product->order_id = $order->order_id;
            $product->datetime = $order->datetime;
            $product->partner_id = $order->partner_id;
            $product->offer_id = $order->offer_id;
            $product->link_id = $order->link_id;
            $product->product_id = $product_id;
            $product->product_name = trim(($product_data['name'] ?? '') . ' ' . ($product_data['variant'] ?? ''));
            $product->category = $product_data['category'] ?? null;
            $product->price = $product_data['price'];
            $product->quantity = $product_data['quantity'] ?? 1;
            $product->total = $product->price * $product->quantity;
            $product->web_id = $order->web_id;
            $product->click_id = $order->click_id;
            $product->pixel_id = $order->pixel_id;
            $product->amount = 0;
            $product->amount_advert = 0;
            $product->fee_advert = 0;
            $product->save();
            logger()->debug('Saved product: ' . $product->product_name);
        }
        $this->pixel_log->is_order = true;
        return true;
    }
}

As you see, I have approximately similar methods in terms of logic and operations. How can I rewrite these methods in the correct way using design patterns KISS, DRY ?

Aucun commentaire:

Enregistrer un commentaire