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/hi.naniguide.com/app/Services/TemplateService.php
<?php

namespace App\Services;

use App\Models\Template;
use App\Models\Customer;
use Illuminate\Pagination\LengthAwarePaginator;

class TemplateService
{
    private function customerGroupIds(Customer $customer): array
    {
        return $customer->customerGroups()
            ->pluck('customer_groups.id')
            ->map(fn ($id) => (int) $id)
            ->values()
            ->all();
    }

    /**
     * Get paginated list of templates for a customer.
     */
    public function getPaginated(Customer $customer, array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        // Get customer's group IDs
        $groupIds = $this->customerGroupIds($customer);

        $query = Template::where(function ($q) use ($customer, $groupIds) {
            $q->where('customer_id', $customer->id)
              ->orWhere(function ($subQ) use ($groupIds) {
                  // Show public templates that are either:
                  // 1. Not restricted to specific groups, OR
                  // 2. Restricted to groups that include the customer's groups
                  $subQ->where('is_public', true)
                       ->where('is_system', false)
                       ->where(function ($groupQuery) use ($groupIds) {
                           $groupQuery->whereDoesntHave('customerGroups') // No restrictions
                                    ->orWhereHas('customerGroups', function ($restrictedQuery) use ($groupIds) {
                                        $restrictedQuery->whereIn('customer_groups.id', $groupIds);
                                    });
                       });
              });
        });

        // Apply filters
        if (isset($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        if (isset($filters['type'])) {
            $query->where('type', $filters['type']);
        }

        return $query->latest()->paginate($perPage);
    }

    /**
     * Create a new template.
     */
    public function create(Customer $customer, array $data): Template
    {
        $settings = [];
        if (isset($data['settings']) && is_array($data['settings'])) {
            $settings = $data['settings'];
        }

        return Template::create([
            'customer_id' => $customer->id,
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'type' => $data['type'] ?? 'email',
            'html_content' => $data['html_content'] ?? null,
            'plain_text_content' => $data['plain_text_content'] ?? null,
            'grapesjs_data' => $data['grapesjs_data'] ?? null,
            'settings' => $settings,
            'is_public' => $data['is_public'] ?? false,
        ]);
    }

    /**
     * Update an existing template.
     */
    public function update(Template $template, array $data): Template
    {
        $settings = is_array($template->settings) ? $template->settings : [];
        if (isset($data['settings']) && is_array($data['settings'])) {
            $settings = array_replace($settings, $data['settings']);
        }

        $template->update([
            'name' => $data['name'] ?? $template->name,
            'description' => $data['description'] ?? $template->description,
            'type' => $data['type'] ?? $template->type,
            'html_content' => $data['html_content'] ?? $template->html_content,
            'plain_text_content' => $data['plain_text_content'] ?? $template->plain_text_content,
            'grapesjs_data' => $data['grapesjs_data'] ?? $template->grapesjs_data,
            'settings' => $settings,
            'is_public' => $data['is_public'] ?? $template->is_public,
        ]);

        return $template->fresh();
    }

    /**
     * Delete a template.
     */
    public function delete(Template $template): bool
    {
        // Don't allow deletion of system templates
        if ($template->is_system) {
            throw new \Exception('Cannot delete system templates.');
        }

        return $template->delete();
    }

    /**
     * Duplicate a template.
     */
    public function duplicate(Template $template, Customer $customer): Template
    {
        // Check if customer has access to this template
        if (!$this->canAccessTemplate($template, $customer)) {
            throw new \Exception('You do not have permission to duplicate this template.');
        }

        $newTemplate = $template->replicate();
        $newTemplate->customer_id = $customer->id;
        $newTemplate->name = $template->name . ' (Copy)';
        $newTemplate->slug = null; // Will be auto-generated
        $newTemplate->is_public = false;
        $newTemplate->is_system = false;
        $newTemplate->usage_count = 0;
        $newTemplate->save();

        return $newTemplate;
    }

    /**
     * Check if customer can access a template.
     */
    public function canAccessTemplate(Template $template, Customer $customer): bool
    {
        // Customer can always access their own templates
        if ($template->customer_id === $customer->id) {
            return true;
        }

        $isSharedTemplate = $template->is_system || $template->is_public;

        if ($isSharedTemplate) {
            $groupIds = $this->customerGroupIds($customer);

            if (!$template->customerGroups()->exists()) {
                return true;
            }

            return $template->customerGroups()
                ->whereIn('customer_groups.id', $groupIds)
                ->exists();
        }

        return false;
    }
}