定制 comsa/sulu-reservations 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

comsa/sulu-reservations

Composer 安装命令:

composer require comsa/sulu-reservations

包简介

Reservation bundle for Sulu

README 文档

README

How it works

What is this bundle?

  • Reservation system
  • Integerated with Sulu FormBundle

The bundles makes use of reservables that you can create. These can be linked to reservable options that you can create as well. The bundle supports single payment and payments per person. Each reservable can have different price groups that have their own price (e.g. adults => €5, children => €3). Payments are configured inside the settings tab of the module. There are 3 types supported which can have their own extra cost (bank, cash or mollie).

Installation

Add to assets/admin/package.json:

"sulu-reservations-bundle": "file:node_modules/@sulu/vendor/comsa/sulu-reservations/Resources/js"

Add to assets/website/package.json:

"sulu-reservations-bundle": "file:../../vendor/comsa/sulu-reservations/Resources/js",

Run npm install in both

Add it to assets/admin/index.js:

import 'sulu-reservations-bundle/admin'

Add it to assets/website/index.js:

import 'sulu-reservations-bundle/website'

And build both it using npm run build, this might take a while :)

Add routes to both routes_admin.yaml and routes_website.yaml

In: config/routes_admin.yaml

sulu_reservations_admin:
  type: rest
  resource: "@SuluReservationsBundle/Resources/config/routes/admin.yaml"
  prefix: /admin/reservations/api

In: config/routes_website.yaml

sulu_reservations_website:
  resource: "@SuluReservationsBundle/Resources/config/routes/website.yaml"
  prefix: /sulu-reservations

Create the following parameter in config/services.yaml and give the correct value:

    comsa_sulu_reservations_mollie_api_key: '%env(COMSA_RE_MOLLIE_API_KEY)%'

Create a template named comsa_reservable (this key is used to generate pages when adding a reservable) and add the following field:

<property name="reservable" type="single_reservable_selection">
    <meta>
        <title lang="en">Reservable</title>
        <title lang="nl">Reserveerbaar Item</title>
    </meta>
</property>

Add the following code in config/services.yaml.

sulu_form.request_listener:
    class: App\EventListener\RequestListener
    arguments:
        - '@sulu_form.builder'
        - '@sulu_form.handler'
        - '@sulu_form.configuration.form_configuration_factory'
        - '@event_dispatcher'
        - '@router.default'
    tags:
        - { name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest' }

This code overwrites the standard RequestListener from the sulu/form-bundle. Create the following file:

<?php

declare(strict_types=1);

namespace App\EventListener;

use Sulu\Bundle\FormBundle\Configuration\FormConfigurationFactory;
use Sulu\Bundle\FormBundle\Entity\Dynamic;
use Sulu\Bundle\FormBundle\Event\DynFormSavedEvent;
use Sulu\Bundle\FormBundle\Form\BuilderInterface;
use Sulu\Bundle\FormBundle\Form\HandlerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\RouterInterface;

class RequestListener
{
    protected BuilderInterface $formBuilder;
    protected HandlerInterface $formHandler;
    protected FormConfigurationFactory $formConfigurationFactory;
    protected EventDispatcherInterface $eventDispatcher;
    protected RouterInterface $router;

    /**
     * RequestListener constructor.
     */
    public function __construct(
        BuilderInterface $formBuilder,
        HandlerInterface $formHandler,
        FormConfigurationFactory $formConfigurationFactory,
        EventDispatcherInterface $eventDispatcher,
        RouterInterface $router
    ) {
        $this->formBuilder = $formBuilder;
        $this->formHandler = $formHandler;
        $this->formConfigurationFactory = $formConfigurationFactory;
        $this->eventDispatcher = $eventDispatcher;
        $this->router = $router;
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMasterRequest()) {
            // do nothing if it's not the master request
            return;
        }

        $request = $event->getRequest();

        if (!$request->isMethod('post')) {
            // do nothing if it's not a post request
            return;
        }

        try {
            $form = $this->formBuilder->buildByRequest($request);

            if (!$form || !$form->isSubmitted() || !$form->isValid()) {
                // do nothing when no form was found or not valid
                return;
            }
        } catch (\Exception $e) {
            // Catch all exception on build form by request
            return;
        }

        /** @var Dynamic $dynamic */
        $dynamic = $form->getData();
        $configuration = $this->formConfigurationFactory->buildByDynamic($dynamic);
        $dynamic->setLocale($request->getLocale()); // Need to be set to request locale for shadow pages, configuraiton will hold the original locale


        if ($this->formHandler->handle($form, $configuration)) {

            if (!$request->request->get("reservable")) {
                $serializedObject = $dynamic->getForm()->serializeForLocale($dynamic->getLocale(), $dynamic);
                $dynFormSavedEvent = new DynFormSavedEvent($serializedObject, $dynamic);
                $this->eventDispatcher->dispatch($dynFormSavedEvent, DynFormSavedEvent::NAME);
                $response = new RedirectResponse('?send=true');
            } else {
                $response = new RedirectResponse($this->router->generate("comsa_sulu_reservations_select_payment_method"));
            }

            $event->setResponse($response);
        }
    }
}

Add the following code to the twig file to render the reservation form written in Vue.js

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

{% block content %}
  {% include '@SuluReservations/reservable.html.twig' %}
{% endblock %}

The following is example code to create a reservable-overview:

XML:

<?xml version="1.0" ?>
<type name="reservable_overview" xmlns="http://schemas.sulu.io/template/template"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/template-1.0.xsd">
    <meta>
        <title lang="en">Reservable overzicht</title>
        <title lang="nl">Reserveerbare items overzicht</title>
    </meta>
    <properties>
        <property name="title" type="text_line">
            <meta>
                <title lang="en">Title</title>
            </meta>
        </property>

        <property name="reservables" type="smart_content">
            <meta>
                <title lang="en">Reservable overview</title>
                <title lang="en">Reserveerbare items overzicht</title>
            </meta>
            <params>
                <param name="provider" value="pages"/>
                <param name="properties" type="collection">
                    <param name="reservable" value="reservable"/>
                </param>
            </params>
        </property>
        <xi:include href="includes/width.xml"/>
    </properties>
</type>

HTML:

<section class="container reservables">
  <h2>{{ block.title }}</h2>
  <ul class="row">
    <table class="d-none d-md-block table table-hover">
      <tr>
        <th>Evenement</th>
        <th>Beschikbare plaatsen</th>
        <th>Start op</th>
        <th>Eindigt op</th>
        <th></th>
      </tr>
      {% for page in block.reservables %}
        {% set spacesLeft = get_spaces_left(page.reservable.id) %}
        <tr>
          <td>{{ page.title }}</td>
          <td>{{ spacesLeft }}</td>
          <td>{{ page.reservable.start|date("d/m/Y") }}</td>
          <td>{{ page.reservable.end|date("d/m/Y") }}</td>
          <td>
            {% if spacesLeft == 0 %}
              <button type="button" class="btn btn-danger">VOLZET</button>
            {% else %}
              <a href="{{ sulu_content_path(page.url) }}" class="btn btn-primary">RESERVEER NU</a>
            {% endif %}
          </td>
        </tr>
      {% endfor %}
    </table>
    {% for page in block.reservables %}
      <li class="col-12 d-md-none">
        <div class="reservable-wrapper">
          <h3>{{ page.title }}</h3>
          <div class="limit">
            {% set spacesLeft = get_spaces_left(page.reservable.id) %}
            <i class="fas fa-user {% if spacesLeft < 5 %} text-danger {% endif %}"></i><span {% if spacesLeft < 5 %} class="text-danger" {% endif %}>{{ spacesLeft }}</span>
          </div>
          <div class="button-wrapper">
            {% if spacesLeft == 0 %}
              <button type="button" class="btn btn-danger">VOLZET</button>
            {% else %}
              <a href="{{ sulu_content_path(page.url) }}" class="btn btn-primary">RESERVEER NU</a>
            {% endif %}
          </div>
        </div>
      </li>
    {% endfor %}
  </ul>
</section>

SCSS:

.reservables {
  margin-left: 0;
  margin-top: 2rem;
  padding: 0;
  width: 100%;

  h3 {
    color: $black;
  }

  ul {
    list-style-type: none;
    padding: 0;
  }

  .reservable-wrapper {
    align-items: center;
    border: solid 1px $gray-500;
    display: flex;
    justify-content: center;
    margin-bottom: 2rem;
    min-height: 14rem;
    padding: 1.5rem;
    width: 100%;

    .button-wrapper {
      bottom: 0;
      position: absolute;
      transform: translateY(-50%);
    }

    .limit {
      border: 1px solid $gray-500;
      border-right: 0;
      border-top: 0;
      min-height: 2rem;
      min-width: 3rem;
      position: absolute;
      right: 0;
      text-align: center;
      top: 0;
      transform: translateX(-35%);
    }

    svg {
      margin-right: 0.5rem;
    }
  }
}

In config/packages/doctrine.yaml:

doctrine:
  orm:
    mappings:
      SuluReservationsBundle:
        is_bundle: true
        type: attribute
        dir: 'Entity'
        prefix: 'Comsa\SuluReservations\Entity'
        alias: SuluReservations

Update your database to add the needed tables using php bin/console doctrine:schema:update -f

Load default settings:

<?php

namespace App\DataFixtures;

use Comsa\SuluReservations\DataFixtures\AppSeed;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

class AppFixtures extends Fixture implements DependentFixtureInterface
{
    public function load(ObjectManager $manager)
    {

    }

    public function getDependencies()
    {
        return[
          AppSeed::class
        ];
    }

}

Copy and paste this into the DataFixtures of your app. Run Symfony console doctrine:fixtures:load --append

统计信息

  • 总下载量: 157
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-12-04

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固