I want to create a discussion when a event is created using the Webbinaro\FlarumCalendar plugin

i have the following in the extend.php

<?php

namespace Mrcaspan\EventToDiscussion;

use Flarum\Extend;
use Webbinaro\FlarumCalendar\Event\EventCreated;
use Flarum\Discussion\Discussion;
use Illuminate\Support\Facades\Log;

return [
    (new Extend\Frontend('forum'))
        ->content(function ($document) {
            // You can add something to the frontend here if needed
        })
    ,
    (new Extend\Listeners())
        ->listen(EventCreated::class, function (EventCreated $event) {
            // Log event data to debug
            Log::info('Event Created:', (array) $event->data);

            // Extract event data
            $eventData = $event->data;

            // Ensure the event has necessary fields
            if (!isset($eventData['title']) || !isset($eventData['description'])) {
                return;
            }

            // Define the "Games" category ID (replace with the correct ID)
            $categoryId = 1; // Replace with your "Games" category ID

            // Create a new discussion based on the event data
            $discussion = Discussion::build([
                'title' => $eventData['title'],
                'content' => $eventData['description'],
                'category_id' => $categoryId,
                'user_id' => $event->actor->id, // The user who created the event
            ]);

            // Save the new discussion
            $discussion->save();

            // Optionally, log the new discussion creation for debugging
            Log::info('Discussion created:', ['discussion_id' => $discussion->id]);
        })
];

I just get an error

Class "Flarum\Extend\Action" not found

I'm new to all this so i could be using it completely wrong!!

  • huseyinfiliz replied to this.
  • [unknown] Do you have access to any documentation that you use for Flarum or do you just read the code to figure out what functions and methods exist?

    Sorry BTW this is in my workbench folder on the site , the plugin is showing and is enabled in the backend!

    MrCaspan I have examined the code in detail for a long time and fixed most of the errors, but I couldn't find a way to listen when a new event is created. I think it would be easier to directly fork the extension and make it an extension that fulfills your request.

    Is it not possible to listen for create events that are from that extension only?

      MrCaspan It doesn't seem possible to extend it, at least. It would be simpler to directly edit the extension itself. I tried a few things, but I couldn't manage to listen for new events.

      Thanks for the help... yeah maybe ill fork it then and just add in the features.. I was hoping to do this so I could provide this for others.

      While the extension doesn't expose a creation event. You can at least use the Laravel model event. You just have to create a service provider (see the example from fof/pages: FriendsOfFlarum/frontpageblob/aad35dffa95c4a269ca4999b84ff22a9ce449978/extend.php#L50-L51, FriendsOfFlarum/frontpageblob/aad35dffa95c4a269ca4999b84ff22a9ce449978/src/Provider/FrontpageSortmapProvider.php)

      And then inside the boot method of the provider

      class MyProvider extends AbstractServiceProvider
      {
          public function boot()
          {
              \Webbinaro\AdvCalendar\Event::created(function (\Webbinaro\AdvCalendar\Event $event) {
                  // your logic here.
              });
          }
      }

        Okay so i created my extend.php like so

        <?php
        
        namespace Mrcaspan\EventToDiscussion;
        
        use Flarum\Extend;
        use Mrcaspan\EventToDiscussion\Providers\EventServiceProvider;
        
        return [
            (new Extend\ServiceProvider())->register(EventServiceProvider::class),
        ];

        Then I created src/Providers/EventServiceProvider.php

        <?php
        
        namespace Mrcaspan\EventToDiscussion\Providers;
        
        use Flarum\Foundation\AbstractServiceProvider;
        use Flarum\Discussion\Discussion;
        use Flarum\Post\CommentPost;
        use Flarum\User\User;
        use Flarum\Tags\Tag;
        use Webbinaro\AdvCalendar\Event;
        
        class EventServiceProvider extends AbstractServiceProvider
        {
            public function boot()
            {
                Event::created(function (Event $event) {
                    // Find the user who created the event
                    $user = User::find($event->user_id);
        
                    if (!$user) {
                        return; // Don't create a discussion if the user is not found
                    }
        
                    // Find the tag (ID = 9)
                    $tag = Tag::find(9);
        
                    if (!$tag) {
                        return; // Don't create a discussion if the tag is missing
                    }
        
                    // Create a new discussion
                    $discussion = new Discussion();
                    $discussion->title = $event->name;
                    $discussion->user_id = $event->user_id;
                    $discussion->save();
        
                    // Attach the tag to the discussion
                    $discussion->tags()->attach($tag->id);
                    $discussion->save();
        
                    // Create the first post in the discussion
                    $post = new CommentPost();
                    $post->content = $event->description ?: 'No description provided.';
                    $post->discussion_id = $discussion->id;
                    $post->user_id = $event->user_id;
                    $post->save();
                });
            }
        }

        I know I am probably butchering this but I need to look at a few more examples to see how others are creating a new discussion!

        Ill add some backend code later to choose the tag ID instead of hard coding it but for now this works for trouble shooting

        okay update:

        src/Providers/EventServiceProvider.php

        This will create the discussion and and the tag to it but I cannot seem to add the first comment to the discussion. I'm actually thinking that maybe I can point the first post to the event post to use the same post for both so that if you edit either one it will be the others. Not sure if this is possible but would like to try Not possible

        <?php
        
        namespace Mrcaspan\EventToDiscussion\Providers;
        
        use Flarum\Foundation\AbstractServiceProvider;
        use Flarum\Discussion\Discussion;
        use Flarum\User\User;
        use Flarum\Tags\Tag;
        use Webbinaro\AdvCalendar\Event;
        use Flarum\Post\Post;
        use Flarum\Post\CommentPost;
        
        class EventServiceProvider extends AbstractServiceProvider
        {
            public function boot()
            {
                Event::created(function (Event $event) {
                    // Get the user who created the event
                    $user = User::find($event->user_id);
                    if (!$user) {
                        return; // Don't create a discussion if the user is not found
                    }
        
                    // Find the tag with ID 9
                    $tag = Tag::find(9);
                    if (!$tag) {
                        return; // Don't create a discussion if the tag is missing
                    }
        
                    // Start the discussion
                    $discussion = Discussion::start($event->name, $user);
                    $discussion->save();
        
                    // Attach the tag to the discussion
                    $discussion->tags()->attach($tag->id);
        
                    // Create the first post for the discussion
                    $post = new CommentPost();
                    $post->discussion_id = $discussion->id;
                    $post->user_id = $user->id;
                    $post->content = $event->description ?: 'No description provided.';
                    $post->is_approved = true; // Mark the post as approved
                    $post->number = 1; // Set post number to 1 (first post)
                    $post->save(); // Save the post
        
                    // Set the post as the first post in the discussion
                    $discussion->setFirstPost($post);
        
                    // Refresh and save the discussion
                    $discussion->refresh();
                    $discussion->save();
                });
            }
        }

          MrCaspan you're refreshing the discussion before saving it, that would mean you're not saving the effects of setFirstPost.

          Remove the refreshing.

          SychO It took me a lot of tries to figure out the logic, but I finally did it!

          @MrCaspan I have tested it many times and I think it works fine.

          composer.json

          {
              "name": "mrcaspan/eventtodiscussion",
              "description": "Creates Flarum discussions automatically when calendar events are created.",
              "type": "flarum-extension",
              "keywords": ["flarum", "calendar", "events", "discussion"],
              "license": "MIT",
              "authors": [
                  {
                      "name": "Name",
                      "email": "mail@gmail.com",
                      "role": "Developer"
                  }
              ],
              "homepage": "#",
              "support": {
                  "issues": "#",
                  "source": "#"
              },
              "require": {
                  "flarum/core": "^1.2.0"
              },
              "autoload": {
                  "psr-4": {
                      "Mrcaspan\\EventToDiscussion\\": "src/"
                  }
              },
              "extra": {
                  "flarum-extension": {
                      "title": "Event to Discussion",
                      "category": "feature",
                      "icon": {
                          "name": "fas fa-calendar-plus",
                          "backgroundColor": "#3498db",
                          "color": "#fff"
                      }
                  }
              }
          }

          extend.php

          <?php
          
          namespace Mrcaspan\EventToDiscussion;
          
          use Flarum\Extend;
          use Illuminate\Contracts\Events\Dispatcher;
          use Mrcaspan\EventToDiscussion\Providers\EventServiceProvider;
          use Mrcaspan\EventToDiscussion\Listeners\EventCreationListener;
          
          return [
              (new Extend\ServiceProvider())
                  ->register(EventServiceProvider::class),
                  
              (new Extend\Event())
                  ->subscribe(EventCreationListener::class),
          ];

          src/Listeners/ EventCreationListener.php

          <?php
          
          namespace Mrcaspan\EventToDiscussion\Listeners;
          
          use Illuminate\Contracts\Events\Dispatcher;
          use Mrcaspan\EventToDiscussion\Event\CalendarEventCreated;
          use Webbinaro\AdvCalendar\Event as CalendarEvent;
          
          class EventCreationListener
          {
              public function subscribe(Dispatcher $events)
              {
                  $events->listen('eloquent.created: Webbinaro\AdvCalendar\Event', [$this, 'onEventCreated']);
              }
          
              public function onEventCreated(CalendarEvent $event)
              {
                  app()->make(Dispatcher::class)->dispatch(new CalendarEventCreated($event));
              }
          }

          src/Providers/EventServiceProvider.php

          <?php
          
          namespace Mrcaspan\EventToDiscussion\Providers;
          
          use Flarum\Foundation\AbstractServiceProvider;
          use Flarum\Discussion\Discussion;
          use Flarum\User\User;
          use Flarum\Tags\Tag;
          use Webbinaro\AdvCalendar\Event as CalendarEvent;
          use Flarum\Post\CommentPost;
          use Illuminate\Events\Dispatcher;
          use Flarum\Settings\SettingsRepositoryInterface;
          use Mrcaspan\EventToDiscussion\Event\CalendarEventCreated;
          
          class EventServiceProvider extends AbstractServiceProvider
          {
              public function register()
              {
                  // empty
              }
          
              public function boot(Dispatcher $events, SettingsRepositoryInterface $settings)
              {
                  // Tag ID 1
                  $tagId = $settings->get('event_to_discussion_tag_id', 1);
          
                  $events->listen(CalendarEventCreated::class, function (CalendarEventCreated $event) use ($tagId) {
                      $this->handleEventCreation($event->event, $tagId);
                  });
              }
          
              protected function handleEventCreation(CalendarEvent $event, $tagId)
              {
                  $eventTitle = $event->name;
                  $eventDescription = $event->description;
                  $userId = $event->user_id;
          
                  // Event bilgileri eksikse iÅŸlemi durdur
                  if (empty($eventTitle) || empty($eventDescription) || empty($userId)) {
                      return;
                  }
          
                  $user = User::find($userId);
                  $tag = Tag::find($tagId);
          
                  // User contol
                  if (!$user) {
                      return;
                  }
          
                  try {
                      $now = new \DateTime();
          
                      // Discussion create
                      $discussion = new Discussion();
                      $discussion->title = $eventTitle;
                      $discussion->user_id = $user->id;
                      $discussion->created_at = $now;
                      $discussion->save();
          
                      // Post create
                      $post = new CommentPost();
                      $post->discussion_id = $discussion->id;
                      $post->number = 1;
                      $post->created_at = $now;
                      $post->user_id = $user->id;
                      $post->type = 'comment';
                      $post->content = $eventDescription;
                      $post->save();
          
                      // Update
                      $discussion->first_post_id = $post->id;
                      $discussion->last_post_id = $post->id;
                      $discussion->last_posted_at = $now;
                      $discussion->last_posted_user_id = $user->id;
                      $discussion->post_number_index = 1;
                      $discussion->comment_count = 1;
          
                      // Add tag
                      if ($tag) {
                          $discussion->tags()->attach($tag->id);
                      }
          
                      $discussion->save();
                  } catch (\Exception $e) {
                      // errors
                  }
              }
          }

          src/Event/CalendarEventCreated.php

          <?php
          
          namespace Mrcaspan\EventToDiscussion\Event;
          
          use Webbinaro\AdvCalendar\Event as CalendarEvent;
          
          class CalendarEventCreated
          {
              public $event;
          
              public function __construct(CalendarEvent $event)
              {
                  $this->event = $event;
              }
          }

          Wow this really helps thank you!! Can you explain so I can learn, why did you make it have so many different classes and listeners? also how do you know to do so many things for a post like setting first and last and user_id and created.. THis is where i get lost, i see all these options but I have no clue when to use them of if I should use them..

          How do you know all the things a discussion or a post need? is there actually documentation somewhere of what is needed for each thing?

            MrCaspan No, there is no simple way. At least not for me.

            I write something and see what’s happening as I go. I get errors and fix them. I check which data is being sent to the database and keep working on it until the problem is solved.

            I’ve spent over about 5 hours trying this. In other words, I’m not a good developer 😄

            I'm an amature coder also so don't feel bad! I just wish we had some code examples to go by because it really helps!

            I appreciate all your help on this helped me realize I was missing a few things!

              MrCaspan While writing something, I also review other open source extensions, especially the FoF extensions.

              @SychO is also a huge help!

              This is what I ended up with

              <?php
              
              namespace Mrcaspan\EventToDiscussion\Providers;
              
              use Flarum\Foundation\AbstractServiceProvider;
              use Flarum\Discussion\Discussion;
              use Flarum\User\User;
              use Flarum\Tags\Tag;
              use Webbinaro\AdvCalendar\Event;
              use Flarum\Post\Post;
              use Flarum\Post\CommentPost;
              
              class EventServiceProvider extends AbstractServiceProvider
              {
                  public function boot()
                  {
                      Event::created(function (Event $event) {
                          // Get the user who created the event
                          $user = User::find($event->user_id);
                          if (!$user) {
                              return; // Don't create a discussion if the user is not found
                          }
              
                          // Find the tag with ID 9
                          $tag = Tag::find(9);
                          if (!$tag) {
                              return; // Don't create a discussion if the tag is missing
                          }
              
                          $eventTitle = $event->name;
                          $eventDescription = $event->description;
                          $now = new \DateTime();
              
                          // Discussion create
                          $discussion = new Discussion();
                          $discussion->title = $eventTitle;
                          $discussion->user_id = $user->id;
                          $discussion->created_at = $now;
                          $discussion->save();
              
                          $post = new CommentPost();
                          $post->discussion_id = $discussion->id;
                          $post->number = 1;
                          $post->created_at = $now;
                          $post->user_id = $user->id;
                          $post->type = 'comment';
                          $post->content = $eventDescription;
                          $post->save();
              
                          // Update
                          $discussion->first_post_id = $post->id;
                          $discussion->last_post_id = $post->id;
                          $discussion->last_posted_at = $now;
                          $discussion->last_posted_user_id = $user->id;
                          $discussion->post_number_index = 1;
                          $discussion->comment_count = 1;
                          $discussion->tags()->attach($tag->id);
              			$discussion->save();
              
                      });
                  }
              }

              again its crude but it does work for learning!!

              Okay so now that this works I have a few tweaks I want to do


              This code hooks into the calendar event after the calendar item is created. Is there a way to intercept the data before it saves it? so I can add or modify the body?

              What I am looking to do is I want to capture the body of the event and make that the body of the discussion but in the event I just want a link to the new discussion it creates.

              This way when you create an event its has a title and the body is a link to the post that this creates!

              NM I figured it out

              <?php
              
              namespace Mrcaspan\EventToDiscussion\Providers;
              
              use Flarum\Foundation\AbstractServiceProvider;
              use Flarum\Discussion\Discussion;
              use Flarum\User\User;
              use Flarum\Tags\Tag;
              use Webbinaro\AdvCalendar\Event;
              use Flarum\Post\Post;
              use Flarum\Post\CommentPost;
              
              class EventServiceProvider extends AbstractServiceProvider
              {
                  public function boot()
                  {
                      // Trigger only when the event is first created
                      Event::created(function (Event $event) {
                          // Get the user who created the event
                          $user = User::find($event->user_id);
                          if (!$user) {
                              return; // Don't create a discussion if the user is not found
                          }
              
                          // Find the tag with ID 9
                          $tag = Tag::find(9);
                          if (!$tag) {
                              return; // Don't create a discussion if the tag is missing
                          }
              
                          $eventTitle = $event->name;
                          $eventDescription = $event->description;
                          $now = new \DateTime();
              
                          // Create the discussion
                          $discussion = new Discussion();
                          $discussion->title = $eventTitle;
                          $discussion->user_id = $user->id;
                          $discussion->created_at = $now;
                          $discussion->save();
              
                          // Create the first post for the discussion
                          $post = new CommentPost();
                          $post->discussion_id = $discussion->id;
                          $post->number = 1;
                          $post->created_at = $now;
                          $post->user_id = $user->id;
                          $post->type = 'comment';
                          $post->content = $eventDescription;
                          $post->save();
              
                          // Update the discussion with the first post details
                          $discussion->first_post_id = $post->id;
                          $discussion->last_post_id = $post->id;
                          $discussion->last_posted_at = $now;
                          $discussion->last_posted_user_id = $user->id;
                          $discussion->post_number_index = 1;
                          $discussion->comment_count = 1;
                          $discussion->tags()->attach($tag->id);
                          $discussion->save();
              
                          // Update the event's description with the relative discussion URL directly
                          $event->description = "\n\n [Link to Game Discussion](/d/{$discussion->id})\n\n";
                          $event->save();
                      });
                  }
              }