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/Model/Funnel.php
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
use App\Library\Traits\HasUid;
use Validator;

/**
 * @property \App\Model\MailList|null $mailList
 */
class Funnel extends Model
{
    use HasFactory;
    use HasUid;
    use SoftDeletes;

    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';

    protected $fillable = [
        'name', 'slug', 'description', 'mail_list_id', 'settings', 'tags',
    ];

    protected $casts = [
        'settings'     => 'array',
        'is_template'  => 'boolean',
        'published_at' => 'datetime',
    ];

    // -------------------------------------------------------------------------
    // Boot
    // -------------------------------------------------------------------------

    protected static function boot()
    {
        parent::boot();

        static::creating(function ($funnel) {
            if (empty($funnel->slug) && $funnel->name) {
                $funnel->slug = $funnel->generateUniqueSlug($funnel->name);
            }
        });
    }

    // -------------------------------------------------------------------------
    // Relationships
    // -------------------------------------------------------------------------

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }

    public function steps()
    {
        return $this->hasMany(FunnelStep::class)->orderBy('sort_order');
    }

    public function mailList()
    {
        return $this->belongsTo(MailList::class, 'mail_list_id');
    }

    public function products()
    {
        return $this->belongsToMany(FunnelProduct::class, 'funnel_product_links')
            ->withPivot('sort_order', 'custom_price')
            ->withTimestamps()
            ->orderBy('funnel_product_links.sort_order');
    }

    public function productLinks()
    {
        return $this->hasMany(FunnelProductLink::class);
    }

    public function domains()
    {
        return $this->hasMany(FunnelDomain::class);
    }

    // -------------------------------------------------------------------------
    // Scopes
    // -------------------------------------------------------------------------

    public function scopeOfCustomer($query, $customer)
    {
        return $query->where('customer_id', $customer->id);
    }

    public function scopePublished($query)
    {
        return $query->whereNotNull('published_at');
    }

    public function scopeDraft($query)
    {
        return $query->whereNull('published_at');
    }

    public function scopeTemplate($query)
    {
        return $query->where('is_template', true);
    }

    public function scopeNotTemplate($query)
    {
        return $query->where('is_template', false);
    }

    public function scopeSearch($query, $keyword)
    {
        if ($keyword) {
            $query->where('name', 'like', '%' . trim($keyword) . '%');
        }
    }

    // -------------------------------------------------------------------------
    // Publish / Draft
    // -------------------------------------------------------------------------

    public function publish()
    {
        $this->published_at = now();
        $this->save();
    }

    public function unpublish()
    {
        $this->published_at = null;
        $this->save();
    }

    public function isPublished(): bool
    {
        return !is_null($this->published_at);
    }

    public function isDraft(): bool
    {
        return is_null($this->published_at);
    }

    // -------------------------------------------------------------------------
    // Factory / CRUD helpers
    // -------------------------------------------------------------------------

    public static function newDefault($customer)
    {
        $funnel = new self();
        $funnel->customer_id = $customer->id;
        $funnel->status = self::STATUS_ACTIVE;

        return $funnel;
    }

    public function fillParams($params)
    {
        $this->name = $params['name'] ?? $this->name;
        $this->description = $params['description'] ?? $this->description;
        $this->tags = $params['tags'] ?? $this->tags;

        if (!empty($params['slug'])) {
            $this->slug = $params['slug'];
        }

        if (array_key_exists('mail_list_uid', $params)) {
            if (!empty($params['mail_list_uid'])) {
                $this->mail_list_id = MailList::findByUid($params['mail_list_uid'])->id;
            } else {
                $this->mail_list_id = null;
            }
        }

        // Merge settings (preserve existing keys not in this request)
        $settings = $this->settings ?? [];
        $settingsKeys = [
            'favicon', 'seo_title', 'seo_description', 'og_image',
            'facebook_pixel_id', 'ga_measurement_id', 'gtm_container_id',
            'webhook_url', 'webhook_events',
            'head_scripts', 'body_scripts',
            'checkout_test_mode',
        ];
        foreach ($settingsKeys as $key) {
            if (array_key_exists("settings_{$key}", $params)) {
                $settings[$key] = $params["settings_{$key}"];
            }
        }
        $this->settings = $settings;
    }

    public function saveFromParams($params)
    {
        $this->fillParams($params);

        $validator = Validator::make($params, [
            'name' => 'required|max:255',
        ]);

        if ($validator->fails()) {
            return $validator;
        }

        $this->save();

        return $validator;
    }

    // -------------------------------------------------------------------------
    // Slug
    // -------------------------------------------------------------------------

    public function generateUniqueSlug($name)
    {
        $slug = Str::slug($name);
        $original = $slug;
        $count = 1;

        while (self::withTrashed()
            ->where('customer_id', $this->customer_id)
            ->where('slug', $slug)
            ->where('id', '!=', $this->id ?? 0)
            ->exists()
        ) {
            $slug = $original . '-' . $count++;
        }

        return $slug;
    }

    // -------------------------------------------------------------------------
    // URL / Entry
    // -------------------------------------------------------------------------

    public function getPublicUrl()
    {
        return url('f/' . $this->slug);
    }

    public function getEntryStep()
    {
        return $this->steps()->where('is_published', true)->orderBy('sort_order')->first();
    }

    // -------------------------------------------------------------------------
    // Duplicate / Clone
    // -------------------------------------------------------------------------

    public function duplicate()
    {
        $copy = $this->replicate(['uid', 'slug', 'published_at', 'deleted_at']);
        $copy->name = $this->name . ' (Copy)';
        $copy->slug = $copy->generateUniqueSlug($copy->name);
        $copy->published_at = null;
        $copy->save();

        // Clone steps with templates
        foreach ($this->steps as $step) {
            $step->duplicateTo($copy);
        }

        // Clone product links
        foreach ($this->productLinks as $link) {
            $newLink = $link->replicate();
            $newLink->funnel_id = $copy->id;
            $newLink->save();
        }

        return $copy;
    }

    public static function cloneFrom($templateFunnel, $customer)
    {
        $funnel = $templateFunnel->replicate(['uid', 'slug', 'published_at', 'deleted_at', 'is_template']);
        $funnel->customer_id = $customer->id;
        $funnel->is_template = false;
        $funnel->slug = $funnel->generateUniqueSlug($templateFunnel->name);
        $funnel->published_at = null;
        $funnel->save();

        foreach ($templateFunnel->steps as $step) {
            $step->duplicateTo($funnel);
        }

        foreach ($templateFunnel->productLinks as $link) {
            $newLink = $link->replicate();
            $newLink->funnel_id = $funnel->id;
            $newLink->save();
        }

        return $funnel;
    }

    // -------------------------------------------------------------------------
    // Cleanup
    // -------------------------------------------------------------------------

    public function deleteAndCleanup()
    {
        foreach ($this->steps as $step) {
            $step->deleteAndCleanup();
        }

        $this->productLinks()->delete();
        $this->domains()->delete();
        $this->delete();
    }
}