kronhyx/fullcalendar-bundle

This package is abandoned and no longer maintained. The author suggests using the dramosv90/fullcalendar-bundle package instead.

FullCalendar integration in Symfony2

Installs: 26

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 3

Language:JavaScript

Type:symfony-bundle

dev-master 2018-05-03 15:13 UTC

This package is not auto-updated.

Last update: 2022-02-01 13:08:43 UTC


README

We want to build a distribuible bundle for Symfony 2 that allow us to show events in the fullCalendar.js (http://fullcalendar.io/) library, calendar and scheduler.

How to use it

Install

php composer.phar require fados-produccions/full-calendar-bundle dev-master

register he bundle inthe appKernel.php

   new Kronhyx\fullCalendarBundle\fullCalendarBundle(),

This bundle has a dependency on the FOSJsRouting bundle to expose the calendar AJAX event loader route. Please ensure that the FOSJsRouting bundle is installed and configured before continuing.

Usage

Configure you config.yml

full_calendar:
     class_manager: AppBundle\Entity\CompanyEvents

In the config.yml you need to put mappings by this way

 orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
              default:
                mappings:
                  fullCalendarBundle: ~

or

orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true

depends on your configuration file config.yml

The class parameter contains the Entity that stores the events, this entity must extends from BaseEvent. Create an entity:

namespace AppBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
use Kronhyx\fullCalendarBundle\Entity\Event as BaseEvent;
 
/**
 * @ORM\Entity
 * @ORM\Table(name="companyEvents")
 */
class CompanyEvents extends BaseEvent
{
 /**
 * @var int
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
 protected $id;
}

Execute from command line, this will create the entity for the calendar

php app/console doctrine:schema:update --force

Register the routing in app/config/routing.yml:

# app/config/routing.yml

fados_fullcalendar:
    resource: "@fullCalendarBundle/Resources/config/routing.xml"

Publish the assets:

$ php app/console assets:install web

Add the required stylesheet and javascripts to your layout:

Stylesheet:

<link rel="stylesheet" href="{{ asset('bundles/fullcalendar/css/fullcalendar.min.css') }}" />
<link rel="stylesheet" href="{{ asset('bundles/fullcalendar/css/fullcalendar.print.css') }}" media="print" />

Javascript:

<script type="text/javascript" src="{{ asset('js/jquery-1.8.1.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/moment.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/fullcalendar.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/init.fullCalendar.js') }}"></script>

Then, in the template where you wish to display the calendar, add the following twig:

{{ fullCalendar() }}

Page sample:

{% extends 'base.html.twig' %}


{% block javascripts %}
    <script type="text/javascript" src="{{ asset('js/jquery-1.8.1.min.js') }}"></script>
    <script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
    <script src="{{ path('fos_js_routing_js', {'callback': 'fos.Router.setData'}) }}"></script>
    <script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/moment.min.js') }}"></script>
    <script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/fullcalendar.min.js') }}"></script>
    <script type="text/javascript" src="{{ asset('bundles/fullcalendar/js/init.fullCalendar.js') }}"></script>
{% endblock %}

{% block body %}
    <div id="wrapper">
        <div id="container">
            <div id="welcome">
                <h1><span>Welcome to</span> Symfony {{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}</h1>
            </div>
        </div>
    </div>

    {{ fullCalendar() }}
{% endblock %}

{% block stylesheets %}
    <link rel="stylesheet" href="{{ asset('bundles/fullcalendar/css/fullcalendar.min.css') }}" />
    <link rel="stylesheet" href="{{ asset('bundles/fullcalendar/css/fullcalendar.print.css') }}" media="print" />
{% endblock %}

Calendar Javascript

The file init.fullCalendar.js in the bundles/fullcalendar/js/ contains two routes, the fullcalendar_loadevents route that is triggered when the Calendar is loaded, fullcalendar_resizedate is triggered when resize event date and the fullcalendar_changedate that is trtiggered when a event is moved.

   events:
        {
            url:Routing.generate('fullcalendar_loadevents', { month: moment().format('MM'), year: moment().format('YYYY') }),
            color: 'blue',
            textColor:'white',
            error: function() {
                alert('Error receving events');
            }
        },
        eventDrop: function(event,delta,revertFunc) {
            var newData = event.start.format('YYYY-MM-DD');
            //var end = (event.end == null) ? start : event.end.format('YYYY-MM-DD');
            $.ajax({
                url: Routing.generate('fullcalendar_changedate'),
                data: { id: event.id, newDate: newData },
                type: 'POST',
                dataType: 'json',
                success: function(response){
                    console.log('ok');
                },
                error: function(e){
                    revertFunc();
                    alert('Error processing your request: '+e.responseText);
                }
            });

        },
        eventResize: function(event, delta, revertFunc) {

            var newData = event.end.format('YYYY-MM-DD');
            $.ajax({
                url: Routing.generate('fullcalendar_resizedate'),
                data: { id: event.id, newDate: newData },
                type: 'POST',
                dataType: 'json',
                success: function(response){
                    console.log('ok');
                },
                error: function(e){
                    revertFunc();
                    alert('Error processing your request: '+e.responseText);
                }
            });

        },
        eventClick: function(calEvent, jsEvent, view) {
            console.log('Event: ' + calEvent.title);
            console.log('Event: ' + calEvent.id);
        },

eventClick is the event triggered when you cluck and event.

You could overwrite this init.calendar.js to fit your needs.

How to create a FullCalendar distribuible Bundle from scratch

Create Bundle

First of all we have to create a Symfony2 project, in our case we use 2.7 version.

php composer.phar create-project symfony/framework-standard-edition bundleFullCalendar "2.7.*

Once installed, we have to create a folder inside the vendor folder where we will build our fullcalendar bundle. We will create in the path vendor/fadosProduccions/fullcalendarbundle/

After create it, we will create the Symfony2 folder structure following coockbook best practices.

Inside the DependencyInjection folder we create two files, fullCalendarExtension.php with all the configuration files that we have to load.

<?php

namespace Kronhyx\fullCalendarBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\Config\FileLocator;

class fullCalendarExtension extends Extension
{
 //Carreguem els serveis
 public function load(array $configs, ContainerBuilder $container)
 {
 $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
 $loader->load('services.yml');
 }
}

and Configuration.php file

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();

        $rootNode = $treeBuilder->root('fullCalendar');
        $rootNode->
        children()
            ->scalarNode('class_manager')
            ->isRequired()
            ->cannotBeEmpty()
            ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}

In this file we configure the parameters that we will need for the fullcalendarbundle, in this case we will configure the class_manager, this parameter is mandatory because is the entity that will be showed in the calendar, this entity must be an extension of baseEvent. This configure.php represents this configuration in the config.yml Configure you config.yml

full_calendar:
     class: appBundle/Entity/CompanyEvents

Finally we have to create fullcalendarbundle.php used for load the bundle:

<?php

namespace Kronhyx\fullCalendarBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class fullcalendarbundle extends Bundle
{

}

Composer.json

The composer.json file should include the following metadata

{
  "name": "fados-produccions/full-calendar-bundle",
  "version":"1.0.0",
  "type": "symfony-bundle",
  "description": "FullCalendar integration in Symfony2",
  "keywords": ["fullCalendar"],
  "homepage": "https://github.com/fados-produccions/fullCalendarbundle",
  "license": "MIT",
  "authors": [
    {
      "name": "Albert Juhé",
      "email": "ajuhe@fadosProduccions.com",
      "homepage": "https://github.com/fados-produccions/fullCalendarbundle"
    }
  ],
 "minimum-stability": "dev",
 "require": {
        "symfony/twig-bundle": "~2.1|~3.0",
        "symfony/framework-bundle": "~2.1|~3.0",
        "friendsofsymfony/jsrouting-bundle": "~1.1",
        "doctrine/collections": ">=1.0"
  },
 "autoload": {
    "psr-0": { "fadosProduccions\\fullCalendarBundle\\": "" }
  },
  "target-dir":"fadosProduccions/fullCalendarBundle",
  "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}

Services

Now we have to create a couple of services, fados.calendar.service manage the entity and the app.fados.twig_extension that allow us to use a twig extension component {{ fullCalendar() }}

services:
  fados.calendar.service:
       class:  Kronhyx\fullCalendarBundle\Services\CalendarManagerRegistry
       arguments: ["@doctrine","@service_container"]
  app.fados.twig_extension:
       class:  Kronhyx\fullCalendarBundle\Twig\fullCalendarExtension
       public: false
       tags:
         - { name: twig.extension }

Twig extension

Now we have to create the twig extension defined previously to use it inside twig {{ fullCalendar }} Create the folder Twig, in this folder we will crate the extesion

<?php

namespace Kronhyx\fullCalendarBundle\Twig;

class fullCalendarExtension extends \Twig_Extension
{
  public function getName() {
  return 'fullCalendar';
 }

  public function getFunctions()
 {

  return array(
  'fullCalendar' => new \Twig_SimpleFunction(
  'fullCalendar',
  array($this, 'fullCalendar'),
  array('is_safe' => array('html'))
 ),
 );
 }

 public function fullCalendar()
 {
  return "<div id='calendar-place'></div>";
 }
}

After this you can register it in the services.yml, an use it. If you want to try it, without normal bundle install, you have to register the bundle first with

'fadosProduccions\\fullcalendarbundle\\' => array($vendorDir . '/fadosProduccions/fullcalendarbundle'),

in the file vendor\composer\autoload_psr4.php

Model and Entity

He have to create the amin entity

<?php

namespace Kronhyx\fullCalendarBundle\Entity;

use Kronhyx\fullCalendarBundle\Model\CalendarEvents as baseCalendarEvent;

abstract class Event extends baseCalendarEvent
{
    /**
     * Convert calendar event details to an array
     *
     * @return array $event
     */

}

that extends from CalendarEvents, this model contains the basic properties for the event.

namespace Kronhyx\fullCalendarBundle\Model;

class CalendarEvents
{
    /**
     * @var string Title/label of the calendar event.
     */
    protected $title;

    /**
     * @var string URL Relative to current path.
     */
    protected $url;

    /**
     * @var string HTML color code for the bg color of the event label.
     */
    protected $bgColor;

    /**
     * @var string HTML color code for the foregorund color of the event label.
     */
    protected $fgColor;

    /**
     * @var string css class for the event label
     */
    protected $cssClass;

    /**
     * @var \DateTime DateTime object of the event start date/time.
     */
    protected $startDatetime;

    /**
     * @var \DateTime DateTime object of the event end date/time.
     */
    protected $endDatetime;

    /**
     * @var boolean Is this an all day event?
     */
    protected $allDay = false;

    public function __construct()
    {

    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getTitle()
    {
        return $this->title;
    }
    public function setUrl($url)
    {
        $this->url = $url;
    }

    public function getUrl()
    {
        return $this->url;
    }

    public function setBgColor($color)
    {
        $this->bgColor = $color;
    }

    public function getBgColor()
    {
        return $this->bgColor;
    }

    public function setFgColor($color)
    {
        $this->fgColor = $color;
    }

    public function getFgColor()
    {
        return $this->fgColor;
    }

    public function setCssClass($class)
    {
        $this->cssClass = $class;
    }

    public function getCssClass()
    {
        return $this->cssClass;
    }

    public function setStartDatetime(\DateTime $start)
    {
        $this->startDatetime = $start;
    }

    public function getStartDatetime()
    {
        return $this->startDatetime;
    }

    public function setEndDatetime(\DateTime $end)
    {
        $this->endDatetime = $end;
    }

    public function getEndDatetime()
    {
        return $this->endDatetime;
    }

    public function setAllDay($allDay = false)
    {
        $this->allDay = (boolean) $allDay;
    }

    public function getAllDay()
    {
        return $this->allDay;
    }

     public function toArray()
    {
        return array(
            'id'               => $this->id,
            'title'            => $this->title,
            'start'            => $this->startDatetime->format("Y-m-d\TH:i:sP"),
            'end'              => $this->endDatetime->format("Y-m-d\TH:i:sP"),
            'url'              => $this->url,
            'backgroundColor'  => $this->bgColor,
            'borderColor'      => $this->bgColor,
            'textColor'        => $this->fgColor,
            'className'        => $this->cssClass,
            'allDay'           => $this->allDay
        );
    }

}

finally we have to map it to the orm, the next file contains the database mapping for the CalendarEvent. This file is in the Kronhyx\fullCalendarBundle\Resources\Config\doctrine\Event.orm.xml

<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping
        xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

    <mapped-superclass name="Kronhyx\fullCalendarBundle\Entity\Event">

        <field name="title" column="title" type="string" length="255" nullable="true"/>
        <field name="url" column="url" type="string" length="255" nullable="true"/>
        <field name="bgColor" column="bgColor" type="string" length="10" nullable="true"/>
        <field name="cssClass" column="cssClass" type="string" length="10" nullable="true"/>
        <field name="startDatetime" column="startDatetime" type="datetime" nullable="false"/>
        <field name="endDatetime" column="endDatetime" type="datetime" nullable="false"/>
        <field name="allDay" column="allDay" type="boolean"/>
    </mapped-superclass>
</doctrine-mapping>

This allow us to create and entity that extends to baseEvent with fields mapped to the database, this mapping is very important , bind the entity with the database mapping.

Before execute this:

php app/console doctrine:schema:update --force

test if you have in your config.yml the auto_mapping: true

orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true

the entity is created in the database with the fields mapped.

Routing

The routing file stores the routes called for the init.fullCalendar.js

  • Routing.generate('fullcalendar_resizedate')
  • Routing.generate('fullcalendar_changedate')
  • Routing.generate('fullcalendar_loadevents', { month: moment().format('MM'), year: moment().format('YYYY') })
<?xml version="1.0" encoding="UTF-8" ?>

<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">

    <route id="fullcalendar_loadevents" pattern="/fullCalendar/load">
        <default key="_controller">fullcalendarbundle:Calendar:load</default>
        <option key="expose">true</option>
    </route>
    <route id="fullcalendar_changedate" pattern="/fullCalendar/change">
        <default key="_controller">fullcalendarbundle:Calendar:change</default>
        <option key="expose">true</option>
    </route>
    <route id="fullcalendar_resizedate" pattern="/fullCalendar/resize">
        <default key="_controller">fullcalendarbundle:Calendar:resize</default>
        <option key="expose">true</option>
    </route>

</routes>

This routing.xml must be called from config.yml to use it: Register the routing in app/config/routing.yml:

# app/config/routing.yml

fados_fullcalendar:
    resource: "@fullcalendarbundle/Resources/config/routing.xml"

The routes called in this file uses the CalendarController, place where we define the action for each route.

Controller

The main controller is Kronhyx\fullCalendarBundle\Controller\CalendarController

This controller uses the service fados.calendar.service to manage the entity.

services:
  fados.calendar.service:
       class:  Kronhyx\fullCalendarBundle\Services\CalendarManagerRegistry
       arguments: ["@doctrine","@service_container"]

the CalendarManagerRegistry receive two parameters:

  • doctrine: ManagerRegistry (Use when you don't know wich entitymanager needs the database entity)
  • service_container: Container (For getting parameters, in this case class_manager)
class CalendarManagerRegistry
{
    protected $managerRegistry;
    protected $container;
    protected $recipient;
    protected $manager;

    public function __construct(ManagerRegistry $managerRegistry, Container $container)
    {
        $this->container = $container;
        $this->recipient = $this->container->getParameter( 'class_manager' );
        $this->managerRegistry = $managerRegistry;
        $this->manager = $this->managerRegistry->getManagerForClass($this->recipient);

    }

Manager contains the entity manager for the class class_manager get it from the config.yml parameters. Later we will use the manager properti to find or save entity in the database, for example:

 public function changeDate($newStartData,$newEndData,$id) {
        $entity = $this->manager->getRepository($this->recipient)->find($id);
        $entity->setStartDatetime(new \DateTime($newStartData));
        $entity->setEndDatetime(new \DateTime($newEndData));
        $this->save($entity);
   }