Buzz-Events

Pacchetto di buzz che gestisce le iscrizioni di generici partecipanti a eventi.

Funzionamento

Installazione

Per fare il seed delle Permissions è stato predisposto un comando di artisan:

php artisan buzz-events:install

Eventi ed edizioni

L'evento è la rappresentazione generale, che normalmente ha un titolo e una descrizione. L'edizione, invece, è la singola occorrenza dell'evento, contenente l'indirizzo, la data in cui si svolgerà, il numero massimo di posti disponibili (-1 nel caso in cui siano indefiniti), quando si apriranno le iscrizioni e quando si chiuderanno e chi è l'organizzatore. Ad esempio:

  • Evento: Sagra di Melere
  • Edizione: edizione anno 2018

E' prevista la possibilità che gli eventi siano su invito. In questo caso l'organizzatore può inviare gli inviti ai partecipanti e i partecipanti possono rispondere all'invito.
Nel caso in cui gli inviti non siano necessari, i partecipanti possono confermare/rifiutare/mettere in forse la loro partecipazione all'evento.

Le edizioni, inoltre, possono avere dei documenti collegati, come la locandina o materiale relativo all'evento (es: materiale di un corso, attestati di partecipazione...).

Partecipanti

I partecipanti vanno registrati nel file config/buzzevents.php, assegnando loro un nome univoco e indicando il model cui fanno riferimento.
Inoltre, i Model indicati come partecipanti devono utilizzare il trait Nodopiano\Buzz\Events\Traits\Participate.

Trait Participate

Il trait participate ha una serie di metodi astratti che vanno implementati all'interno del Model per garantire il corretto funzionamento dei partecipanti all'interno del pacchetto. Si è scelto di delegare al Model la gestione particolare legata alla visualizzazione, identificazione e autorizzazione dell'oggetto in questione.

abstract function getTypeAttribute();
abstract function displayedName();
abstract function toApiArray();
abstract static function getRepositoryClass();
abstract function canBeSubsribedBy($user);
abstract static function getParticipantConnectedTo($user);
abstract static function getParticipantFromRequest($request);
getTypeAttribute()

É necessario indicare una stringa che identifichi la tipologia di partecipante. Ad esempio, se stiamo trattando un partecipante di tipo guest, una possibile implementazione può essere:

    public function getTypeAttribute()
    {
        return 'guest';
    }
displayedName()

Il nome da visualizzare per identificare il particolare oggetto.

    public function displayedName()
    {
        return $this->surname . ' ' . $this->name;
    }
toApiArray()

Api decoration: array da mostrare nelle api quando si chiede la lista dei partecipanti ad un'edizione di un corso.

    public function toApiArray()
    {
        return [
            'id' => $this->id,
            'type' => 'guest',
            'nome' => $this->nome,
            'cognome' => $this->cognome,
            'email' => $this->email,
            'telefono' => $this->telefono,
        ];
    }
getRepositoryClass()

Riferimento alla classe Repository legata al Model.

    public static function getRepositoryClass()
    {
        return 'Nodopiano\BuzzPreset\Repositories\Repository';
    }
canBeSubsribedBy($user)

Implementare la logica per decidere se l'utente in argomento è autorizzato ad iscrivere il partecipante al corso.

    public function canBeSubsribedBy($user)
    {
        return $user->id == $this->user->id;
    }
getParticipantConnectedTo($user)

Indicare, se esiste, il partecipante collegato all'utente in argomento

    public function canBeSubsribedBy($user)
    {
        return optional($user)->albo;
    }
getParticipantFromRequest($request)

Ricavare l'oggetto partecipante dalla request. (Avrei potuto farlo con il repository.)

public static function getParticipantFromRequest($request)
    {
        if ($request->nome && $request->cognome && $request->email) {
            return self::create($request->all());
        }

        if ($request->id) {
            return self::find($request->id);
        }

        return null;
    }

WIP: Relazione polimorfica

I partecipanti sono in relazione con le edizioni per mezzo di una versione modificata della relazione molti a molti polimorfica (BelongsToManyMorph) la quale risolve il polimorfismo della classe Participant in fase di risoluzione della query. Per questo motivo, quando si richiede $edition->participants si ottiene una Collection di oggetti diversi, a seconda del tipo di partecipante che è collegato all'edizione.

WIP: Al momento, tuttavia, questa relazione supporta solo la risoluzione tramite i metodi get() e paginate(), mentre l'utilizzo di funzioni come where genera un errore ed è consigliabile applicarle DOPO aver chiamato la funzione get().

Stati

Al momento gli stati sono i seguenti:

  • Pending: L'invito è stato inviato, ma non c'è stata risposta da parte del partecipante.
  • Refused: Il partecipante non intende partecipare.
  • Maybe: Il partecipante non sa se parteciperà.
  • Confirmed: Il partecipante ha confermato la sua presenza e i posti disponibili non sono ancora esauriti.
  • Waiting: Il partecipante ha confermato la sua presenza ma i posti disponibili sono esauriti.

Se si liberano dei posti diponibili, i partecipanti in stato waiting possono essere spostati nello stato confirmed dall'organizzatore.

Personalizzazione

Configurazione

All'interno del file config/buzzevents.php è possibile indicare, sia per gli Eventi che per le Edizioni:

  • name: nome da mostrare nelle routes
  • creation_request: form request per la creazione di un nuovo elemento
  • update_request: form request per l'update di un elemento
  • api_resource: l'api resource per il Model in questione
  • search_fields: i campi in cui verrà fatta la ricerca nelle api
  • results_per_page: quanti risultati per pagina
  • extra_fields: campi aggiuntivi da gestire con BuzzAttributes

Eventi

Ad ogni variazione di stato viene emesso un evento:

  • InviteSent
  • ParticipateToEvent
  • ParticipateNotToEvent
  • ParticipateMaybeToEvent
  • WaitForEvent
  • MovedToConfirmed

Documentazione endpoint API

Event

Senza login

  • GET: /eventi
  • GET: /eventi/{id}

Solo utenti admin

  • POST: /eventi
    • struttura payload: {title: string|required, description: text, coordinator: string}
  • POST: /eventi/{id}
    • struttura payload: {title: string|required, description: text, coordinator: string}
  • DELETE : /eventi/{id}
    • struttura payload: null

Edition

Senza login

  • GET: /edizioni
  • GET: /edizioni/{id}

Solo utenti admin

  • POST: /edizioni
    • struttura payload:
      { 
          available_seats: integer(-1 is infinite)|required,
          registrations_open: date(YYYY-mm-dd HH:mm:ss)|required,
          registrations_close: date(YYYY-mm-dd HH:mm:ss)|required,
          address: string|required,
          coordinator_id: integer,
          event_id: integer|required,
          latitude: required,
          longitude: required,
          note: string,
          featured_img: base64,
          days: [
              {
                  id: integer,
                  date: date(YYYY-mm-dd)|required,
                  start_hour: hour(HH:mm:ss)|required,
                  end_hour: hour(HH:mm:ss)|required,
              }
          ]
      }
      
  • POST: /edizioni/{id}
    • struttura payload: come sopra
  • DELETE : /edizioni/{id}
    • struttura payload: null
  • DELETE : /edizioni/{id}/featured -> elimina immagine in evidenza dell'edizione
    • struttura payload: null

Participants

Utenti loggati

  • GET: /edizioni/{id}/partecipanti*
  • POST: /edizioni/{id}/partecipanti*
    • struttura payload: {id: id|required, type: type|required (ex: App/User)}
  • DELETE: /edizioni/{id}/partecipanti*
    • struttura payload: {id: id|required, type: type|required (ex: App/User)}
  • POST: /edizioni/{id}/invitati*
    • struttura payload: {type: type|required (ex: App/User), altri campi} -> altri campi dipendono dall'implementazione del metodo getParticipantFromRequest($request) nel Model che implementa il trait Participate.
  • DELETE: /edizioni/{id}/invitati*
    • struttura payload: come sopra.

* (solo se il partecipante può essere gestito dall'utente loggato; altrimenti è richiesto il ruolo di amministratore )

Solo utenti admin

  • POST: /edizioni/{id}/partecipanti/move
    • struttura payload: {id: id|required, type: type|required (ex: App/User)}

Editions of Event

Senza login

  • GET: /eventi/{id}/edizioni

Participants of Edition

Utenti loggati

  • GET: /partecipanti/{type}/{id}/edizioni*

* (solo se il partecipante può essere gestito dall'utente loggato; altrimenti è richiesto il ruolo di amministratore )

Documents of Edition

Utenti loggati

  • GET: /edizioni/{id}/documenti

Solo utenti admin

  • POST: /edizioni/{id}/documenti
    • struttura payload: {title: string|required, file: base64|requiredwithout link, link: string|requiredwithout file}
  • DELETE: /edizioni/{id}/documenti/{id}
    • struttura payload: null