HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Services/Ads/AdCampaignService.php
<?php

namespace App\Services\Ads;

use App\Model\AdAudience;
use App\Model\AdCampaign;
use App\Model\AdCreative;
use App\Model\AdPlatform;
use App\Model\LocalCustomer;
use Illuminate\Support\Str;

class AdCampaignService
{
    public function create(LocalCustomer $customer, array $data): AdCampaign
    {
        $campaign = new AdCampaign();
        $campaign->uid = uniqid();
        $campaign->customer_id = $customer->id;
        $campaign->name = $data['name'];
        $campaign->objective = $data['objective'];
        $campaign->status = AdCampaign::STATUS_DRAFT;

        if (isset($data['daily_budget'])) {
            $campaign->daily_budget = $data['daily_budget'];
        }
        if (isset($data['lifetime_budget'])) {
            $campaign->lifetime_budget = $data['lifetime_budget'];
        }
        if (isset($data['budget_currency'])) {
            $campaign->budget_currency = $data['budget_currency'];
        }
        if (isset($data['bid_strategy'])) {
            $campaign->bid_strategy = $data['bid_strategy'];
        }
        if (isset($data['schedule_start'])) {
            $campaign->schedule_start = $data['schedule_start'];
        }
        if (isset($data['schedule_end'])) {
            $campaign->schedule_end = $data['schedule_end'];
        }
        if (isset($data['utm_campaign'])) {
            $campaign->utm_campaign = $data['utm_campaign'];
        }

        // R5.1 — wizard-driven creative + audience selection.  FormRequest
        // already enforces tenant scope on the UIDs; here we just resolve
        // them to row IDs and set the FKs.  Both nullable: empty wizard
        // step yields null binding.
        if (!empty($data['ad_creative_uid'])) {
            $creative = AdCreative::where('uid', $data['ad_creative_uid'])
                ->where('customer_id', $customer->id)
                ->first();
            if ($creative !== null) {
                $campaign->ad_creative_id = $creative->id;
            }
        }
        if (!empty($data['ad_audience_uid'])) {
            $audience = AdAudience::where('uid', $data['ad_audience_uid'])
                ->where('customer_id', $customer->id)
                ->first();
            if ($audience !== null) {
                $campaign->ad_audience_id = $audience->id;
            }
        }

        $campaign->save();

        // R5.1 — wizard-driven multi-platform attach.  FormRequest already
        // tenant-scoped each UID; we attach pivot rows after save() so the
        // belongsToMany sync has a campaign id to anchor on.
        if (!empty($data['ad_platform_uids']) && is_array($data['ad_platform_uids'])) {
            $platformIds = AdPlatform::whereIn('uid', $data['ad_platform_uids'])
                ->where('customer_id', $customer->id)
                ->where('status', AdPlatform::STATUS_ACTIVE)
                ->pluck('id')
                ->all();
            if ($platformIds !== []) {
                $campaign->platforms()->sync($platformIds);
            }
        }

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.created',
            status: 'success',
            title: 'Campaign created: ' . $campaign->name,
            platform: null,
        );

        return $campaign;
    }

    public function update(AdCampaign $campaign, array $data): AdCampaign
    {
        $fillable = ['name', 'objective', 'daily_budget', 'lifetime_budget',
            'budget_currency', 'bid_strategy', 'bid_amount',
            'schedule_start', 'schedule_end', 'utm_source', 'utm_medium', 'utm_campaign'];

        foreach ($fillable as $field) {
            if (array_key_exists($field, $data)) {
                $campaign->{$field} = $data[$field];
            }
        }

        $campaign->save();

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.updated',
            status: 'success',
            title: 'Campaign updated: ' . $campaign->name,
        );

        return $campaign;
    }

    public function delete(AdCampaign $campaign): void
    {
        $name = $campaign->name;
        $campaign->delete();

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.deleted',
            status: 'info',
            title: 'Campaign deleted: ' . $name,
        );
    }

    public function copy(AdCampaign $campaign): AdCampaign
    {
        $copy = $campaign->replicate(['uid', 'published_at']);
        $copy->uid = uniqid();
        $copy->name = $campaign->name . ' (Copy)';
        $copy->status = AdCampaign::STATUS_DRAFT;
        $copy->published_at = null;
        $copy->save();

        AdActivityLogger::log(
            entity: $copy,
            action: 'campaign.copied',
            status: 'success',
            title: 'Campaign copied from: ' . $campaign->name,
        );

        return $copy;
    }

    public function archive(AdCampaign $campaign): void
    {
        $campaign->status = AdCampaign::STATUS_ARCHIVED;
        $campaign->save();

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.archived',
            status: 'info',
            title: 'Campaign archived: ' . $campaign->name,
        );
    }

    public function pause(AdCampaign $campaign): void
    {
        $campaign->status = AdCampaign::STATUS_PAUSED;
        $campaign->save();

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.paused',
            status: 'info',
            title: 'Campaign paused: ' . $campaign->name,
        );
    }

    public function resume(AdCampaign $campaign): void
    {
        $campaign->status = AdCampaign::STATUS_ACTIVE;
        $campaign->save();

        AdActivityLogger::log(
            entity: $campaign,
            action: 'campaign.resumed',
            status: 'success',
            title: 'Campaign resumed: ' . $campaign->name,
        );
    }
}