Search code examples
dependency-injectionlaminas

How to use my custom google calendar module into another custom todo module in Laminas MVC?


I've created a Calendar module in laminas MVC which interacts with Google Calendar and then created another Todo module which is supposed to interact with my Calendar module. The signature of CalendarController in Calendar module is like

    public function __construct(
        ListProcess $listProcess,
        AddProcess $addProcess,
        EditProcess $editProcess,
        DeleteProcess $deleteProcess
    ) 

Now my code in Todo module that is supposed to initiate the scheduling process is as below

public function execute(): array
    {
        $todo = json_decode((new CrmApiService())->getTodo($this->getTodoId()), true);
        $eventData["summary"] = $todo->title;
        $eventData["description"] = $todo->content;
        $eventData["startDateTime"] = $todo->nextActionDate;
        $eventData["endDateTime"] = $todo->nextActionDate;
        $calendar = new CalendarController();

        return $calendar->scheduleFromAnotherSource($eventData);
    }

when I execute this, I get an error like below

Too few arguments to function CalendarModule\Controller\CalendarController::__construct(), 0 passed in D:\laminas\todo-module-integrated\vendor\iss-module\todo-module\src\Process\TodoScheduleProcess.php on line 53 and exactly 4 expected

I know that I'm not supposed to call the CalendarController directly rather it should be through a Service.

My question is, how should I create a Service in Todo module that has the dependency on Calendar module and it should interact with Calendar module without requiring the involvement of CalendarController which has further dependencies?


Solution

  • Thanks for all the help.

    Here's how I've implemented it. (May it'll help someone)

    In my Calendar-module, the logic of adding is separate from CalendarController and its called AddProcess, this is how I add an event from the controller. $result = $this->addProcess->execute($this->params()->fromPost());. The Google authentication is being handled through a separate service CalendarClientService. All my processes access this service to authenticate as below and then get executed.

    $client = $this->calendarClientService->getClient();
    if (!$this->calendarClientService->authenticateClient($client)) {
        return ["error" => "authentication", "url" => filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL)];
    }
    

    Now I've created a new service in Calendar-module as below where I just called AddProcess and passed it the new eventData.

    class CalendarService
    {
        protected AddProcess $addProcess;
    
        public function __construct(AddProcess $addProcess)
        {
            $this->addProcess = $addProcess;
        }
    
        public function scheduleAsEvent($eventData)
        {
            $eventData["startDateTime"] = Carbon::parse($eventData["startDateTime"])->format("Y-m-d\TH:i");
            $eventData["endDateTime"] = Carbon::parse($eventData["endDateTime"])->format("Y-m-d\TH:i");
    
            return $this->addProcess->execute($eventData);
        }
    }
    

    Then from my Todo-module, I access this service as below

    namespace TodoModule\Process;
    
    use Carbon\Carbon;
    use Google\Exception;
    use Laminas\Cache\Exception\ExceptionInterface;
    use Laminas\Mvc\Controller\AbstractActionController;
    use CalendarModule\Service\CalendarService;
    use TodoModule\Service\CrmApiService;
    
    class TodoScheduleProcess extends AbstractActionController
    {
        protected int $todoID;
    
        protected CalendarService $calendarService;
    
        public function __construct(CalendarService $calendarService)
        {
            $this->calendarService = $calendarService;
        }
    
        public function execute(): array
        {
            $todo = json_decode((new CrmApiService())->getTodo($this->getTodoId()));
            $eventData["summary"] = $todo->title;
            $eventData["description"] = $todo->content;
            $eventData["startDateTime"] = $todo->nextActionDate;
            $eventData["endDateTime"] = $todo->nextActionDate;
    
            return $this->calendarService->scheduleAsEvent($eventData);
        }
    
        public function getTodoId()
        {
            return $this->todoID;
        }
    
        public function setTodoId($id)
        {
            $this->todoID = $id;
        }
    }```