EscolaLMS/Courses

View on GitHub
src/Services/TopicService.php

Summary

Maintainability
A
1 hr
Test Coverage
B
83%
<?php

namespace EscolaLms\Courses\Services;

use EscolaLms\Courses\Models\Topic;
use EscolaLms\Courses\Models\TopicResource;
use EscolaLms\Courses\Repositories\Contracts\TopicRepositoryContract;
use EscolaLms\Courses\Repositories\Contracts\TopicResourceRepositoryContract;
use EscolaLms\Courses\Services\Contracts\TopicServiceContract;
use EscolaLms\TopicTypes\Models\TopicContent\AbstractTopicFileContent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;

class TopicService implements TopicServiceContract
{
    protected TopicRepositoryContract $topicRepository;
    protected TopicResourceRepositoryContract $topicResourceRep;

    public function __construct(
        TopicRepositoryContract $topicRepository,
        TopicResourceRepositoryContract $topicResourceRep
    ) {
        $this->topicRepository = $topicRepository;
        $this->topicResourceRep = $topicResourceRep;
    }

    public function cloneTopic(Topic $topic): Model
    {
        $clonedTopicArray = $topic->replicate()->toArray();
        unset($clonedTopicArray['order']);
        /** @var Topic $clonedTopic */
        $clonedTopic = $this->topicRepository->create($clonedTopicArray);
        $clonedTopicable = $topic->topicable->replicate();

        if (class_exists(AbstractTopicFileContent::class) && $clonedTopicable instanceof AbstractTopicFileContent) {
            foreach ($clonedTopicable->getFileKeyNames() as $fileKeyName) {
                if (Storage::exists($clonedTopicable->{$fileKeyName})) {
                    $to = $clonedTopic->getStorageDirectoryAttribute() . basename($clonedTopicable->{$fileKeyName});
                    Storage::copy($clonedTopicable->{$fileKeyName}, $to);
                    $clonedTopicable->{$fileKeyName} = $to;
                }
            }
        }

        $clonedTopicable->save();
        $clonedTopic->topicable_id = $clonedTopicable->getKey();
        $clonedTopic->topicable_type = get_class($clonedTopicable);
        $clonedTopic->save();

        foreach ($topic->resources as $resource) {
            if (Storage::exists($resource->path)) {
                $this->cloneTopicResource($clonedTopic, $resource);
            }
        }

        return $clonedTopic;
    }

    private function cloneTopicResource(Topic $clonedTopic, TopicResource $topicResource): Model
    {
        $pathFrom = $topicResource->path;
        $pathTo = $clonedTopic->getStorageDirectoryAttribute() . 'resources' . DIRECTORY_SEPARATOR . $topicResource->name;

        Storage::copy($pathFrom, $pathTo);

        $topicResourceData = $topicResource->replicate()->toArray();
        $topicResourceData['topic_id'] = $clonedTopic->getKey();
        $topicResourceData['path'] = $pathTo;

        return $this->topicResourceRep->create($topicResourceData);
    }
}