add customer api

This commit is contained in:
Roland Schneider 2019-10-08 22:33:25 +02:00 committed by Roland Schneider
parent 9aee187d11
commit 1300bfc752
33 changed files with 1164 additions and 246 deletions

5
.gitignore vendored
View File

@ -49,9 +49,10 @@ phpunit.phar
/rest/web/assets/** /rest/web/assets/**
!/rest/web/assets/.gitkeep !/rest/web/assets/.gitkeep
/customerapi/web/assets/**
!/customerapi/web/assets/.gitkeep
/customerapi/config/*-local.php /customerapi/config/*-local.php
/customerapi/runtime/logs/** /customerapi/runtime/logs/**
!/customerapi/runtime/.gitkeep !/customerapi/runtime/.gitkeep
/customerapi/web/assets/**
!/customerapi/assets/.gitkeep

View File

@ -81,6 +81,7 @@ class EventRegistrationController extends Controller
* If update is successful, the browser will be redirected to the 'view' page. * If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id * @param integer $id
* @return mixed * @return mixed
* @throws NotFoundHttpException
*/ */
public function actionUpdate($id) public function actionUpdate($id)
{ {

View File

@ -0,0 +1,131 @@
<?php
namespace common\components;
class HttpStatus
{
// const CONTINUE = 100;
const SWITCHING_PROTOCOLS = 101;
const PROCESSING = 102; // RFC2518
const OK = 200;
const CREATED = 201;
const ACCEPTED = 202;
const NON_AUTHORITATIVE_INFORMATION = 203;
const NO_CONTENT = 204;
const RESET_CONTENT = 205;
const PARTIAL_CONTENT = 206;
const MULTI_STATUS = 207; // RFC4918
const ALREADY_REPORTED = 208; // RFC5842
const IM_USED = 226; // RFC3229
const MULTIPLE_CHOICES = 300;
const MOVED_PERMANENTLY = 301;
const FOUND = 302;
const SEE_OTHER = 303;
const NOT_MODIFIED = 304;
const USE_PROXY = 305;
const RESERVED = 306;
const TEMPORARY_REDIRECT = 307;
const PERMANENTLY_REDIRECT = 308; // RFC7238
const BAD_REQUEST = 400;
const UNAUTHORIZED = 401;
const PAYMENT_REQUIRED = 402;
const FORBIDDEN = 403;
const NOT_FOUND = 404;
const METHOD_NOT_ALLOWED = 405;
const NOT_ACCEPTABLE = 406;
const PROXY_AUTHENTICATION_REQUIRED = 407;
const REQUEST_TIMEOUT = 408;
const CONFLICT = 409;
const GONE = 410;
const LENGTH_REQUIRED = 411;
const PRECONDITION_FAILED = 412;
const REQUEST_ENTITY_TOO_LARGE = 413;
const REQUEST_URI_TOO_LONG = 414;
const UNSUPPORTED_MEDIA_TYPE = 415;
const REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const EXPECTATION_FAILED = 417;
const I_AM_A_TEAPOT = 418; // RFC2324
const UNPROCESSABLE_ENTITY = 422; // RFC4918
const LOCKED = 423; // RFC4918
const FAILED_DEPENDENCY = 424; // RFC4918
const RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817
const UPGRADE_REQUIRED = 426; // RFC2817
const PRECONDITION_REQUIRED = 428; // RFC6585
const TOO_MANY_REQUESTS = 429; // RFC6585
const REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
const INTERNAL_SERVER_ERROR = 500;
const NOT_IMPLEMENTED = 501;
const BAD_GATEWAY = 502;
const SERVICE_UNAVAILABLE = 503;
const GATEWAY_TIMEOUT = 504;
const VERSION_NOT_SUPPORTED = 505;
const VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295
const INSUFFICIENT_STORAGE = 507; // RFC4918
const LOOP_DETECTED = 508; // RFC5842
const NOT_EXTENDED = 510; // RFC2774
const NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585
}

View File

@ -3,10 +3,16 @@
namespace common\manager; namespace common\manager;
use common\models\Card; use common\models\Card;
use common\models\CardEventRegistrationForm;
use common\models\Customer; use common\models\Customer;
use common\models\Event; use common\models\Event;
use common\models\EventRegistration; use common\models\EventRegistration;
use common\models\Ticket; use common\models\Ticket;
use Exception;
use Throwable;
use Yii;
use yii\base\Object;
use yii\db\ActiveRecord;
use yii\db\Query; use yii\db\Query;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
@ -18,7 +24,7 @@ use yii\web\ServerErrorHttpException;
* Date: 2018.12.17. * Date: 2018.12.17.
* Time: 6:12 * Time: 6:12
*/ */
class EventRegistrationManager extends \yii\base\Object class EventRegistrationManager extends Object
{ {
const CARD_NOT_FOUND = 1; const CARD_NOT_FOUND = 1;
const CUSTOMER_NOT_FOUND = 2; const CUSTOMER_NOT_FOUND = 2;
@ -31,70 +37,70 @@ class EventRegistrationManager extends \yii\base\Object
const EVENT_UNAVAILABLE = 9; const EVENT_UNAVAILABLE = 9;
public static $STATES = [ public static $STATES = [
self::CARD_NOT_FOUND => "CARD_NOT_FOUND", self::CARD_NOT_FOUND => 'CARD_NOT_FOUND',
self::CUSTOMER_NOT_FOUND => "CUSTOMER_NOT_FOUND", self::CUSTOMER_NOT_FOUND => 'CUSTOMER_NOT_FOUND',
self::TICKET_NOT_FOUND => "TICKET_NOT_FOUND", self::TICKET_NOT_FOUND => 'TICKET_NOT_FOUND',
self::NO_FREE_SEATS => "NO_FREE_SEATS", self::NO_FREE_SEATS => 'NO_FREE_SEATS',
self::EVENT_TYPE_NOT_FOUND => "EVENT_TYPE_NOT_FOUND", self::EVENT_TYPE_NOT_FOUND => 'EVENT_TYPE_NOT_FOUND',
self::TICKET_INSUFFICIENT => "TICKET_INSUFFICIENT", self::TICKET_INSUFFICIENT => 'TICKET_INSUFFICIENT',
self::UNKNOWN_ERROR => "UNKNOWN_ERROR", self::UNKNOWN_ERROR => 'UNKNOWN_ERROR',
self::MAX_SEAT_COUNT_EXCEEDED => "MAX_SEAT_COUNT_EXCEEDED", self::MAX_SEAT_COUNT_EXCEEDED => 'MAX_SEAT_COUNT_EXCEEDED',
self::EVENT_UNAVAILABLE => "EVENT_UNAVAILABLE", self::EVENT_UNAVAILABLE => 'EVENT_UNAVAILABLE',
]; ];
/** /**
* @param \common\models\CardEventRegistrationForm $cardEventForm * @param CardEventRegistrationForm $cardEventForm
* @throws \yii\db\Exception * @throws Exception
*/ */
public function registerCard($cardEventForm) public function registerCard($cardEventForm)
{ {
$db = \Yii::$app->db; $db = Yii::$app->db;
$tx = $db->beginTransaction(); $tx = $db->beginTransaction();
try { try {
if ($cardEventForm->validate()) { if ($cardEventForm->validate()) {
/** @var \common\models\Card $card */ /** @var Card $card */
$card = Card::readCard($cardEventForm->card_number, false); $card = Card::readCard($cardEventForm->card_number, false);
if (!isset($card)) { if (!isset($card)) {
throw new NotFoundHttpException("Card not found: " . $cardEventForm->card_number, self::CARD_NOT_FOUND); throw new NotFoundHttpException('Card not found: ' . $cardEventForm->card_number, self::CARD_NOT_FOUND);
} }
if ($card->isFree()) { if ($card->isFree()) {
throw new NotFoundHttpException("Customer not found", self::CUSTOMER_NOT_FOUND); throw new NotFoundHttpException('Customer not found', self::CUSTOMER_NOT_FOUND);
} }
$activeTickets = $card->getActiveTickets(); $activeTickets = $card->getActiveTickets();
if (sizeof($activeTickets) == 0) { if (count($activeTickets) === 0) {
throw new NotFoundHttpException("Ticket not found", self::TICKET_NOT_FOUND); throw new NotFoundHttpException('Ticket not found', self::TICKET_NOT_FOUND);
} }
/** @var \common\models\Event $event */ /** @var Event $event */
$event = Event::find()->andWhere(['id' => $cardEventForm->event_id])->one(); $event = Event::find()->andWhere(['id' => $cardEventForm->event_id])->one();
if (!isset($event)) { if (!isset($event)) {
throw new NotFoundHttpException("Event not found: " . $cardEventForm->event_id); throw new NotFoundHttpException('Event not found: ' . $cardEventForm->event_id);
} }
if ( isset($event->deleted_at)){ if ( isset($event->deleted_at)){
throw new BadRequestHttpException("Event deleted", self::EVENT_UNAVAILABLE); throw new BadRequestHttpException('Event deleted', self::EVENT_UNAVAILABLE);
} }
if (!$event->hasFreeSeats()) { if (!$event->hasFreeSeats()) {
throw new BadRequestHttpException("No free seats", self::NO_FREE_SEATS); throw new BadRequestHttpException('No free seats', self::NO_FREE_SEATS);
} }
$eventType = $event->eventType; $eventType = $event->eventType;
if (!isset($eventType)) { if (!isset($eventType)) {
throw new ServerErrorHttpException("Event type not found", self::EVENT_TYPE_NOT_FOUND); throw new ServerErrorHttpException('Event type not found', self::EVENT_TYPE_NOT_FOUND);
} }
$selectedTicket = $eventType->findTicketAllowingEventType($activeTickets); $selectedTicket = $eventType->findTicketAllowingEventType($activeTickets);
if (!isset($selectedTicket)) { if (!isset($selectedTicket)) {
throw new NotFoundHttpException("Ticket not found", self::TICKET_INSUFFICIENT); throw new NotFoundHttpException('Ticket not found', self::TICKET_INSUFFICIENT);
} }
if ($selectedTicket->hasOpenReservationCount()) { if ($selectedTicket->hasOpenReservationCount()) {
@ -106,16 +112,17 @@ class EventRegistrationManager extends \yii\base\Object
$registration->id_event = $event->id; $registration->id_event = $event->id;
$registration->id_card = $card->id_card; $registration->id_card = $card->id_card;
$registration->id_ticket = $selectedTicket->id_ticket; $registration->id_ticket = $selectedTicket->id_ticket;
$registration->id_customer = $card->customer->id_customer;
try { try {
$registration->save(false); $registration->save(false);
} catch (\Throwable $exception) { } catch (Throwable $exception) {
throw new ServerErrorHttpException("Failed to save", self::UNKNOWN_ERROR); throw new ServerErrorHttpException('Failed to save', self::UNKNOWN_ERROR);
} }
$cardEventForm->registration = $registration; $cardEventForm->registration = $registration;
} }
$tx->commit(); $tx->commit();
} catch (\Exception $exception) { } catch (Exception $exception) {
$tx->rollBack(); $tx->rollBack();
throw $exception; throw $exception;
} }
@ -126,21 +133,21 @@ class EventRegistrationManager extends \yii\base\Object
{ {
$query = new Query(); $query = new Query();
$query->select([ $query->select([
"event_registration.id as event_registration_id", 'event_registration.id as event_registration_id',
"event_registration.created_at as event_registration_created_at", 'event_registration.created_at as event_registration_created_at',
"event_registration.canceled_at as event_registration_canceled_at", 'event_registration.canceled_at as event_registration_canceled_at',
"event_registration.deleted_at as event_registration_deleted_at", 'event_registration.deleted_at as event_registration_deleted_at',
"card.id_card as card_id_card", 'card.id_card as card_id_card',
"card.number as card_number", 'card.number as card_number',
"customer.id_customer as customer_id_customer", 'customer.id_customer as customer_id_customer',
"customer.name as customer_name", 'customer.name as customer_name',
"customer.email as customer_email", 'customer.email as customer_email',
]); ]);
$query->from(EventRegistration::tableName()); $query->from(EventRegistration::tableName());
$query->innerJoin(Event::tableName(), "event_registration.id_event = event.id"); $query->innerJoin(Event::tableName(), 'event_registration.id_event = event.id');
$query->innerJoin(Card::tableName(), "event_registration.id_card = card.id_card"); $query->innerJoin(Card::tableName(), 'event_registration.id_card = card.id_card');
$query->innerJoin(Customer::tableName(), "customer.id_customer_card = card.id_card"); $query->innerJoin(Customer::tableName(), 'customer.id_customer_card = card.id_card');
$query->andWhere(["event_registration.id_event" => $idEvent]); $query->andWhere(['event_registration.id_event' => $idEvent]);
return $query; return $query;
} }
@ -148,21 +155,21 @@ class EventRegistrationManager extends \yii\base\Object
/** /**
* @param $idRegistration * @param $idRegistration
* @return array|EventRegistration|\yii\db\ActiveRecord|null * @return array|EventRegistration|ActiveRecord|null
* @throws NotFoundHttpException * @throws NotFoundHttpException
*/ */
public function loadRegistration($idRegistration) public function loadRegistration($idRegistration)
{ {
$registration = EventRegistration::find()->andWhere(['id' => $idRegistration])->one(); $registration = EventRegistration::find()->andWhere(['id' => $idRegistration])->one();
if ($registration == null) { if ( $registration === null) {
throw new NotFoundHttpException('The requested registration does not exist.'); throw new NotFoundHttpException('The requested registration does not exist.');
} }
return $registration; return $registration;
} }
/** /**
* @param \common\models\EventRegistration $registration * @param EventRegistration $registration
* @throws ServerErrorHttpException * @throws ServerErrorHttpException
*/ */
public function cancelRegistration($registration) public function cancelRegistration($registration)
@ -181,7 +188,7 @@ class EventRegistrationManager extends \yii\base\Object
} }
/** /**
* @param \common\models\EventRegistration $registration * @param EventRegistration $registration
* @throws ServerErrorHttpException * @throws ServerErrorHttpException
*/ */
public function deleteRegistration($registration) public function deleteRegistration($registration)
@ -202,13 +209,13 @@ class EventRegistrationManager extends \yii\base\Object
/** /**
* Delete an event * Delete an event
* @param \common\models\Event $event * @param Event $event
* @throws \yii\db\Exception * @throws Exception
* @throws \Exception * @throws Throwable
*/ */
public function deleteEvent($event) public function deleteEvent($event)
{ {
$db = \Yii::$app->db; $db = Yii::$app->db;
$tx = $db->beginTransaction(); $tx = $db->beginTransaction();
try { try {
@ -217,20 +224,20 @@ class EventRegistrationManager extends \yii\base\Object
// if even has no registrations // if even has no registrations
// we can simply delete it from db // we can simply delete it from db
// //////////////////////////////// // ////////////////////////////////
if (count($registrations) == 0) { if ( count($registrations) === 0 ) {
$event->delete(); $event->delete();
} else { } else {
$event->deleted_at = date('Y-m-d H:i:s'); $event->deleted_at = date('Y-m-d H:i:s');
$event->save(false); $event->save(false);
foreach ($registrations as $registration) { foreach ($registrations as $registration) {
if (!isset($registration->deleted_at)) { if (!isset($registration->deleted_at)) {
/** @var \common\models\EventRegistration $registration */ /** @var EventRegistration $registration */
$this->deleteRegistration($registration); $this->deleteRegistration($registration);
} }
} }
} }
$tx->commit(); $tx->commit();
} catch (\Exception $e) { } catch (Exception $e) {
$tx->rollBack(); $tx->rollBack();
throw $e; throw $e;
} }

View File

@ -1,6 +1,7 @@
<?php <?php
namespace common\models; namespace common\models;
use common\components\Helper; use common\components\Helper;
use yii\base\Model;
/** /**
* Created by IntelliJ IDEA. * Created by IntelliJ IDEA.
@ -9,7 +10,7 @@ use common\components\Helper;
* Time: 6:14 * Time: 6:14
*/ */
class CardEventRegistrationForm extends \yii\base\Model class CardEventRegistrationForm extends Model
{ {
public $card_number; public $card_number;
public $event_id; public $event_id;

View File

@ -211,13 +211,13 @@ class Customer extends BaseFitnessActiveRecord implements IdentityInterface
/** /**
* Finds an identity by the given ID. * Finds an identity by the given ID.
* @param string|integer $id the ID to be looked for * @param string|integer $id the ID to be looked for
* @return void the identity object that matches the given ID. * @return Customer
* Null should be returned if such an identity cannot be found * Null should be returned if such an identity cannot be found
* or the identity is not in an active state (disabled, deleted, etc.) * or the identity is not in an active state (disabled, deleted, etc.)
*/ */
public static function findIdentity($id) public static function findIdentity($id)
{ {
Customer::findOne($id); return self::findOne(['email' => $id]);
} }
/** /**

View File

@ -111,18 +111,18 @@ class Event extends \yii\db\ActiveRecord
} }
public function getEventType(){ public function getEventType(){
return $this->hasOne(EventType::className(),['id' => 'id_event_type']); return $this->hasOne($this->getEventTypeClass(),['id' => 'id_event_type']);
} }
public function getTrainer(){ public function getTrainer(){
return $this->hasOne(Trainer::className(),['id' => 'id_trainer']); return $this->hasOne($this->getTrainerClass(),['id' => 'id_trainer']);
} }
/** /**
* @return Room|\yii\db\ActiveQuery * @return Room|\yii\db\ActiveQuery
*/ */
public function getRoom() { public function getRoom() {
return $this->hasOne(Room::className(),['id' => 'id_room']); return $this->hasOne($this->getRoomClass(),['id' => 'id_room']);
} }
/** /**
@ -139,16 +139,24 @@ class Event extends \yii\db\ActiveRecord
return $this->hasMany(EventRegistration::className(),['id_event' => 'id']); return $this->hasMany(EventRegistration::className(),['id_event' => 'id']);
} }
/**
* @return \common\models\EventRegistration[]|\yii\db\ActiveQuery
*/
public function getActiveEventRegistrations(){
return $this->hasMany(EventRegistration::className(),['id_event' => 'id'])->andWhere(
[
'event_registration.canceled_at' => null,
'event_registration.deleted_at' => null,
]
);
}
/** /**
* @return \common\models\EventRegistration[]|\yii\db\ActiveQuery * @return \common\models\EventRegistration[]|\yii\db\ActiveQuery
*/ */
public function getEventRegistrationCount(){ public function getEventRegistrationCount(){
return sizeof($this->getEventRegistrations() return sizeof($this->getActiveEventRegistrations()->all());
->andWhere( [
'canceled_at' => null,
'deleted_at' => null,
])
->all());
} }
public function getOpenSeatCount(){ public function getOpenSeatCount(){
@ -183,4 +191,16 @@ class Event extends \yii\db\ActiveRecord
return true; return true;
} }
protected function getTrainerClass(){
return Trainer::class;
}
protected function getEventTypeClass(){
return EventType::class;
}
protected function getRoomClass(){
return Room::class;
}
} }

View File

@ -65,4 +65,14 @@ class EventRegistration extends \yii\db\ActiveRecord
], ],
parent::behaviors()); parent::behaviors());
} }
public function getEvent(){
return $this->hasOne(Event::class,['id' => 'id_event']);
}
public function getCustomer(){
return $this->hasOne(Customer::class,['id' => 'id_customer']);
}
} }

View File

@ -14,8 +14,8 @@
}, },
"minimum-stability": "stable", "minimum-stability": "stable",
"require": { "require": {
"php": ">=5.4.0", "php": ">=5.6.0",
"yiisoft/yii2": "2.0.6", "yiisoft/yii2": "~2.0.10",
"yiisoft/yii2-bootstrap": "*", "yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-swiftmailer": "*", "yiisoft/yii2-swiftmailer": "*",
"kartik-v/yii2-widgets": "^3.4", "kartik-v/yii2-widgets": "^3.4",
@ -31,7 +31,10 @@
"os/php-excel": "^2.1", "os/php-excel": "^2.1",
"phpoffice/phpexcel": "^1.8", "phpoffice/phpexcel": "^1.8",
"2amigos/yii2-tinymce-widget": "~1.1", "2amigos/yii2-tinymce-widget": "~1.1",
"iisns/yii2-assets-compress": "*" "iisns/yii2-assets-compress": "*",
"yiisoft/yii2-composer": "2.0.4",
"sizeg/yii2-jwt": "^2.0",
"fxp/composer-asset-plugin": "dev-master"
}, },
"require-dev": { "require-dev": {
"yiisoft/yii2-codeception": "*", "yiisoft/yii2-codeception": "*",

454
composer.lock generated
View File

@ -1,11 +1,10 @@
{ {
"_readme": [ "_readme": [
"This file locks the dependencies of your project to a known state", "This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "6f107bd4aac24595297e9f71bfd031f3", "content-hash": "62617dd27b81a8c6428c875f01cf0dd8",
"content-hash": "42a9442876f84ea41b6767df22460fcf",
"packages": [ "packages": [
{ {
"name": "2amigos/yii2-tinymce-widget", "name": "2amigos/yii2-tinymce-widget",
@ -65,19 +64,19 @@
"yii 2", "yii 2",
"yii2" "yii2"
], ],
"time": "2015-03-28 21:53:43" "time": "2015-03-28T21:53:43+00:00"
}, },
{ {
"name": "almasaeed2010/adminlte", "name": "almasaeed2010/adminlte",
"version": "v2.3.2", "version": "v2.3.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/almasaeed2010/AdminLTE.git", "url": "https://github.com/ColorlibHQ/AdminLTE.git",
"reference": "1ee281b3b99e8d8cccdc72fb8437c6888149cb46" "reference": "1ee281b3b99e8d8cccdc72fb8437c6888149cb46"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/almasaeed2010/AdminLTE/zipball/1ee281b3b99e8d8cccdc72fb8437c6888149cb46", "url": "https://api.github.com/repos/ColorlibHQ/AdminLTE/zipball/1ee281b3b99e8d8cccdc72fb8437c6888149cb46",
"reference": "1ee281b3b99e8d8cccdc72fb8437c6888149cb46", "reference": "1ee281b3b99e8d8cccdc72fb8437c6888149cb46",
"shasum": "" "shasum": ""
}, },
@ -105,7 +104,7 @@
"theme", "theme",
"web" "web"
], ],
"time": "2015-10-23 14:50:49" "time": "2015-10-23T14:50:49+00:00"
}, },
{ {
"name": "bassjobsen/bootstrap-3-typeahead", "name": "bassjobsen/bootstrap-3-typeahead",
@ -141,7 +140,7 @@
} }
], ],
"description": "Bootstrap 3 Typeahead", "description": "Bootstrap 3 Typeahead",
"time": "2015-11-14 22:02:27" "time": "2015-11-14T22:02:27+00:00"
}, },
{ {
"name": "bower-asset/accounting", "name": "bower-asset/accounting",
@ -245,6 +244,66 @@
], ],
"description": "Font Awesome" "description": "Font Awesome"
}, },
{
"name": "bower-asset/inputmask",
"version": "3.3.11",
"source": {
"type": "git",
"url": "https://github.com/RobinHerbots/Inputmask.git",
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/5e670ad62f50c738388d4dcec78d2888505ad77b",
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b",
"shasum": ""
},
"require": {
"bower-asset/jquery": ">=1.7"
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"./dist/inputmask/inputmask.js",
"./dist/inputmask/inputmask.extensions.js",
"./dist/inputmask/inputmask.date.extensions.js",
"./dist/inputmask/inputmask.numeric.extensions.js",
"./dist/inputmask/inputmask.phone.extensions.js",
"./dist/inputmask/jquery.inputmask.js",
"./dist/inputmask/global/document.js",
"./dist/inputmask/global/window.js",
"./dist/inputmask/phone-codes/phone.js",
"./dist/inputmask/phone-codes/phone-be.js",
"./dist/inputmask/phone-codes/phone-nl.js",
"./dist/inputmask/phone-codes/phone-ru.js",
"./dist/inputmask/phone-codes/phone-uk.js",
"./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jqlite.js",
"./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jquery.js",
"./dist/inputmask/dependencyLibs/inputmask.dependencyLib.js",
"./dist/inputmask/bindings/inputmask.binding.js"
],
"bower-asset-ignore": [
"**/*",
"!dist/*",
"!dist/inputmask/*",
"!dist/min/*",
"!dist/min/inputmask/*"
]
},
"license": [
"http://opensource.org/licenses/mit-license.php"
],
"description": "Inputmask is a javascript library which creates an input mask. Inputmask can run against vanilla javascript, jQuery and jqlite.",
"keywords": [
"form",
"input",
"inputmask",
"jquery",
"mask",
"plugins"
],
"time": "2017-11-21T11:46:23+00:00"
},
{ {
"name": "bower-asset/jquery", "name": "bower-asset/jquery",
"version": "2.1.4", "version": "2.1.4",
@ -314,58 +373,6 @@
"bower-asset-ignore": [] "bower-asset-ignore": []
} }
}, },
{
"name": "bower-asset/jquery.inputmask",
"version": "3.1.63",
"source": {
"type": "git",
"url": "https://github.com/RobinHerbots/jquery.inputmask.git",
"reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/RobinHerbots/jquery.inputmask/zipball/c40c7287eadc31e341ebbf0c02352eb55b9cbc48",
"reference": "c40c7287eadc31e341ebbf0c02352eb55b9cbc48",
"shasum": ""
},
"require": {
"bower-asset/jquery": ">=1.7"
},
"type": "bower-asset-library",
"extra": {
"bower-asset-main": [
"./dist/inputmask/jquery.inputmask.js",
"./dist/inputmask/jquery.inputmask.extensions.js",
"./dist/inputmask/jquery.inputmask.date.extensions.js",
"./dist/inputmask/jquery.inputmask.numeric.extensions.js",
"./dist/inputmask/jquery.inputmask.phone.extensions.js",
"./dist/inputmask/jquery.inputmask.regex.extensions.js"
],
"bower-asset-ignore": [
"**/.*",
"qunit/",
"nuget/",
"tools/",
"js/",
"*.md",
"build.properties",
"build.xml",
"jquery.inputmask.jquery.json"
]
},
"license": [
"http://opensource.org/licenses/mit-license.php"
],
"description": "jquery.inputmask is a jquery plugin which create an input mask.",
"keywords": [
"form",
"input",
"inputmask",
"jquery",
"mask",
"plugins"
]
},
{ {
"name": "bower-asset/moment", "name": "bower-asset/moment",
"version": "2.10.6", "version": "2.10.6",
@ -541,16 +548,16 @@
}, },
{ {
"name": "cebe/markdown", "name": "cebe/markdown",
"version": "1.1.0", "version": "1.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/cebe/markdown.git", "url": "https://github.com/cebe/markdown.git",
"reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2" "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/cebe/markdown/zipball/54a2c49de31cc44e864ebf0500a35ef21d0010b2", "url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86",
"reference": "54a2c49de31cc44e864ebf0500a35ef21d0010b2", "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -568,7 +575,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.1.x-dev" "dev-master": "1.2.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -597,7 +604,7 @@
"markdown", "markdown",
"markdown-extra" "markdown-extra"
], ],
"time": "2015-03-06 05:28:07" "time": "2018-03-26T11:24:36+00:00"
}, },
{ {
"name": "cebe/yii2-gravatar", "name": "cebe/yii2-gravatar",
@ -640,7 +647,7 @@
"gravatar", "gravatar",
"yii" "yii"
], ],
"time": "2013-12-10 17:49:58" "time": "2013-12-10T17:49:58+00:00"
}, },
{ {
"name": "dmstr/yii2-adminlte-asset", "name": "dmstr/yii2-adminlte-asset",
@ -694,25 +701,28 @@
"extension", "extension",
"yii2" "yii2"
], ],
"time": "2015-11-06 10:35:36" "time": "2015-11-06T10:35:36+00:00"
}, },
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
"version": "v4.6.0", "version": "v4.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git", "url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "6f389f0f25b90d0b495308efcfa073981177f0fd" "reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6f389f0f25b90d0b495308efcfa073981177f0fd", "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"reference": "6f389f0f25b90d0b495308efcfa073981177f0fd", "reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.2" "php": ">=5.2"
}, },
"require-dev": {
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
},
"type": "library", "type": "library",
"autoload": { "autoload": {
"psr-0": { "psr-0": {
@ -724,7 +734,7 @@
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"LGPL" "LGPL-2.1-or-later"
], ],
"authors": [ "authors": [
{ {
@ -738,7 +748,66 @@
"keywords": [ "keywords": [
"html" "html"
], ],
"time": "2013-11-30 08:25:19" "time": "2019-07-14T18:58:38+00:00"
},
{
"name": "fxp/composer-asset-plugin",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/fxpio/composer-asset-plugin.git",
"reference": "886ece037849d3935c5a34cdcd984e46f2de5fae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/886ece037849d3935c5a34cdcd984e46f2de5fae",
"reference": "886ece037849d3935c5a34cdcd984e46f2de5fae",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0",
"php": ">=5.3.3"
},
"require-dev": {
"composer/composer": "^1.6.0"
},
"type": "composer-plugin",
"extra": {
"class": "Fxp\\Composer\\AssetPlugin\\FxpAssetPlugin",
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"Fxp\\Composer\\AssetPlugin\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "François Pluchino",
"email": "francois.pluchino@gmail.com"
}
],
"description": "NPM/Bower Dependency Manager for Composer",
"homepage": "https://github.com/fxpio/composer-asset-plugin",
"keywords": [
"asset",
"bower",
"composer",
"dependency manager",
"nodejs",
"npm",
"package"
],
"time": "2019-08-08T18:36:07+00:00"
}, },
{ {
"name": "iisns/yii2-assets-compress", "name": "iisns/yii2-assets-compress",
@ -785,7 +854,7 @@
"iisns", "iisns",
"yii2" "yii2"
], ],
"time": "2016-02-12 14:59:50" "time": "2016-02-12T14:59:50+00:00"
}, },
{ {
"name": "kartik-v/bootstrap-fileinput", "name": "kartik-v/bootstrap-fileinput",
@ -833,7 +902,7 @@
"progress", "progress",
"upload" "upload"
], ],
"time": "2015-09-13 17:39:44" "time": "2015-09-13T17:39:44+00:00"
}, },
{ {
"name": "kartik-v/bootstrap-star-rating", "name": "kartik-v/bootstrap-star-rating",
@ -874,7 +943,7 @@
"jquery", "jquery",
"star" "star"
], ],
"time": "2015-09-21 09:06:33" "time": "2015-09-21T09:06:33+00:00"
}, },
{ {
"name": "kartik-v/dependent-dropdown", "name": "kartik-v/dependent-dropdown",
@ -916,7 +985,7 @@
"option", "option",
"select" "select"
], ],
"time": "2015-07-14 09:54:25" "time": "2015-07-14T09:54:25+00:00"
}, },
{ {
"name": "kartik-v/yii2-krajee-base", "name": "kartik-v/yii2-krajee-base",
@ -962,7 +1031,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-06-16 05:19:57" "time": "2015-06-16T05:19:57+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-activeform", "name": "kartik-v/yii2-widget-activeform",
@ -1009,7 +1078,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-10-22 14:36:24" "time": "2015-10-22T14:36:24+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-affix", "name": "kartik-v/yii2-widget-affix",
@ -1058,7 +1127,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-09 04:56:27" "time": "2014-11-09T04:56:27+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-alert", "name": "kartik-v/yii2-widget-alert",
@ -1108,7 +1177,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-19 06:44:12" "time": "2014-11-19T06:44:12+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-colorinput", "name": "kartik-v/yii2-widget-colorinput",
@ -1157,7 +1226,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-08 21:10:18" "time": "2014-11-08T21:10:18+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-datepicker", "name": "kartik-v/yii2-widget-datepicker",
@ -1206,7 +1275,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-07-19 04:49:03" "time": "2015-07-19T04:49:03+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-datetimepicker", "name": "kartik-v/yii2-widget-datetimepicker",
@ -1255,7 +1324,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-01-25 16:36:55" "time": "2015-01-25T16:36:55+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-depdrop", "name": "kartik-v/yii2-widget-depdrop",
@ -1304,7 +1373,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-06-26 20:20:32" "time": "2015-06-26T20:20:32+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-fileinput", "name": "kartik-v/yii2-widget-fileinput",
@ -1354,7 +1423,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-06-26 20:23:24" "time": "2015-06-26T20:23:24+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-growl", "name": "kartik-v/yii2-widget-growl",
@ -1403,7 +1472,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-05-03 08:23:04" "time": "2015-05-03T08:23:04+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-rangeinput", "name": "kartik-v/yii2-widget-rangeinput",
@ -1452,7 +1521,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-08 21:15:27" "time": "2014-11-08T21:15:27+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-rating", "name": "kartik-v/yii2-widget-rating",
@ -1503,7 +1572,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-08 19:30:37" "time": "2014-11-08T19:30:37+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-select2", "name": "kartik-v/yii2-widget-select2",
@ -1551,7 +1620,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-09-12 19:56:48" "time": "2015-09-12T19:56:48+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-sidenav", "name": "kartik-v/yii2-widget-sidenav",
@ -1600,7 +1669,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-09 08:07:23" "time": "2014-11-09T08:07:23+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-spinner", "name": "kartik-v/yii2-widget-spinner",
@ -1648,7 +1717,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-09 05:02:05" "time": "2014-11-09T05:02:05+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-switchinput", "name": "kartik-v/yii2-widget-switchinput",
@ -1698,7 +1767,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-01-14 16:27:26" "time": "2015-01-14T16:27:26+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-timepicker", "name": "kartik-v/yii2-widget-timepicker",
@ -1747,7 +1816,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-08 20:01:29" "time": "2014-11-08T20:01:29+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-touchspin", "name": "kartik-v/yii2-widget-touchspin",
@ -1797,7 +1866,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-12-04 12:53:04" "time": "2014-12-04T12:53:04+00:00"
}, },
{ {
"name": "kartik-v/yii2-widget-typeahead", "name": "kartik-v/yii2-widget-typeahead",
@ -1845,7 +1914,7 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2015-06-28 18:05:41" "time": "2015-06-28T18:05:41+00:00"
}, },
{ {
"name": "kartik-v/yii2-widgets", "name": "kartik-v/yii2-widgets",
@ -1907,7 +1976,62 @@
"widget", "widget",
"yii2" "yii2"
], ],
"time": "2014-11-09 19:54:17" "time": "2014-11-09T19:54:17+00:00"
},
{
"name": "lcobucci/jwt",
"version": "3.3.1",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/a11ec5f4b4d75d1fcd04e133dede4c317aac9e18",
"reference": "a11ec5f4b4d75d1fcd04e133dede4c317aac9e18",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-openssl": "*",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "^5.7 || ^7.3",
"squizlabs/php_codesniffer": "~2.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"time": "2019-05-24T18:30:49+00:00"
}, },
{ {
"name": "mpdf/mpdf", "name": "mpdf/mpdf",
@ -1950,7 +2074,7 @@
"php", "php",
"utf-8" "utf-8"
], ],
"time": "2015-03-01 10:27:49" "time": "2015-03-01T10:27:49+00:00"
}, },
{ {
"name": "mrclay/minify", "name": "mrclay/minify",
@ -1995,7 +2119,7 @@
], ],
"description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers",
"homepage": "http://code.google.com/p/minify/", "homepage": "http://code.google.com/p/minify/",
"time": "2016-03-08 11:49:57" "time": "2016-03-08T11:49:57+00:00"
}, },
{ {
"name": "natxet/CssMin", "name": "natxet/CssMin",
@ -2042,7 +2166,7 @@
"css", "css",
"minify" "minify"
], ],
"time": "2015-09-25 11:13:11" "time": "2015-09-25T11:13:11+00:00"
}, },
{ {
"name": "os/php-excel", "name": "os/php-excel",
@ -2079,7 +2203,7 @@
"keywords": [ "keywords": [
"excel" "excel"
], ],
"time": "2012-05-02 20:42:37" "time": "2012-05-02T20:42:37+00:00"
}, },
{ {
"name": "phpoffice/phpexcel", "name": "phpoffice/phpexcel",
@ -2136,7 +2260,8 @@
"xls", "xls",
"xlsx" "xlsx"
], ],
"time": "2015-05-01 07:00:55" "abandoned": "phpoffice/phpspreadsheet",
"time": "2015-05-01T07:00:55+00:00"
}, },
{ {
"name": "rmrevin/yii2-fontawesome", "name": "rmrevin/yii2-fontawesome",
@ -2188,7 +2313,51 @@
"font", "font",
"yii" "yii"
], ],
"time": "2015-11-20 09:17:45" "time": "2015-11-20T09:17:45+00:00"
},
{
"name": "sizeg/yii2-jwt",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sizeg/yii2-jwt.git",
"reference": "28830a6eaa66e8b0b08c392d180fc361559de56e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sizeg/yii2-jwt/zipball/28830a6eaa66e8b0b08c392d180fc361559de56e",
"reference": "28830a6eaa66e8b0b08c392d180fc361559de56e",
"shasum": ""
},
"require": {
"lcobucci/jwt": "~3.3.0",
"php": ">=5.6.0",
"yiisoft/yii2": "~2.0.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"type": "yii2-extension",
"autoload": {
"psr-4": {
"sizeg\\jwt\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"authors": [
{
"name": "Dmitriy Demin",
"email": "sizemail@gmail.com",
"homepage": "https://sizeg.tk"
}
],
"description": "JWT based on Icobucci",
"keywords": [
"jwt",
"yii 2",
"yii2"
],
"time": "2019-09-21T06:50:31+00:00"
}, },
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
@ -2241,7 +2410,7 @@
"mail", "mail",
"mailer" "mailer"
], ],
"time": "2015-06-06 14:19:39" "time": "2015-06-06T14:19:39+00:00"
}, },
{ {
"name": "tedivm/jshrink", "name": "tedivm/jshrink",
@ -2287,7 +2456,7 @@
"javascript", "javascript",
"minifier" "minifier"
], ],
"time": "2015-07-04 07:35:09" "time": "2015-07-04T07:35:09+00:00"
}, },
{ {
"name": "tinymce/tinymce", "name": "tinymce/tinymce",
@ -2333,33 +2502,34 @@
"tinymce", "tinymce",
"wysiwyg" "wysiwyg"
], ],
"time": "2016-05-10 11:15:05" "time": "2016-05-10T11:15:05+00:00"
}, },
{ {
"name": "yiisoft/yii2", "name": "yiisoft/yii2",
"version": "2.0.6", "version": "2.0.27",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/yiisoft/yii2-framework.git", "url": "https://github.com/yiisoft/yii2-framework.git",
"reference": "f42b2eb80f61992438661b01d0d74c6738e2ff38" "reference": "6793f8f9b4cd891dbf475cfbb88cf480f74eaa85"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/f42b2eb80f61992438661b01d0d74c6738e2ff38", "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/6793f8f9b4cd891dbf475cfbb88cf480f74eaa85",
"reference": "f42b2eb80f61992438661b01d0d74c6738e2ff38", "reference": "6793f8f9b4cd891dbf475cfbb88cf480f74eaa85",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"bower-asset/jquery": "2.1.*@stable | 1.11.*@stable", "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
"bower-asset/jquery.inputmask": "3.1.*", "bower-asset/jquery": "3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
"bower-asset/punycode": "1.3.*", "bower-asset/punycode": "1.3.*",
"bower-asset/yii2-pjax": ">=2.0.1", "bower-asset/yii2-pjax": "~2.0.1",
"cebe/markdown": "~1.0.0 | ~1.1.0", "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0",
"ext-ctype": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ezyang/htmlpurifier": "4.6.*", "ezyang/htmlpurifier": "~4.6",
"lib-pcre": "*", "lib-pcre": "*",
"php": ">=5.4.0", "php": ">=5.4.0",
"yiisoft/yii2-composer": "*" "yiisoft/yii2-composer": "~2.0.4"
}, },
"bin": [ "bin": [
"yii" "yii"
@ -2413,6 +2583,17 @@
"name": "Paul Klimov", "name": "Paul Klimov",
"email": "klimov.paul@gmail.com", "email": "klimov.paul@gmail.com",
"role": "Core framework development" "role": "Core framework development"
},
{
"name": "Dmitry Naumenko",
"email": "d.naumenko.a@gmail.com",
"role": "Core framework development"
},
{
"name": "Boudewijn Vahrmeijer",
"email": "info@dynasource.eu",
"homepage": "http://dynasource.eu",
"role": "Core framework development"
} }
], ],
"description": "Yii PHP Framework Version 2", "description": "Yii PHP Framework Version 2",
@ -2421,7 +2602,7 @@
"framework", "framework",
"yii2" "yii2"
], ],
"time": "2015-08-05 22:00:30" "time": "2019-09-18T13:04:16+00:00"
}, },
{ {
"name": "yiisoft/yii2-bootstrap", "name": "yiisoft/yii2-bootstrap",
@ -2471,24 +2652,24 @@
"bootstrap", "bootstrap",
"yii2" "yii2"
], ],
"time": "2015-09-23 17:48:24" "time": "2015-09-23T17:48:24+00:00"
}, },
{ {
"name": "yiisoft/yii2-composer", "name": "yiisoft/yii2-composer",
"version": "2.0.3", "version": "2.0.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/yiisoft/yii2-composer.git", "url": "https://github.com/yiisoft/yii2-composer.git",
"reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be" "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/ca8d23707ae47d20b0454e4b135c156f6da6d7be", "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/7452fd908a5023b8bb5ea1b123a174ca080de464",
"reference": "ca8d23707ae47d20b0454e4b135c156f6da6d7be", "reference": "7452fd908a5023b8bb5ea1b123a174ca080de464",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"composer-plugin-api": "1.0.0" "composer-plugin-api": "^1.0"
}, },
"type": "composer-plugin", "type": "composer-plugin",
"extra": { "extra": {
@ -2518,7 +2699,7 @@
"extension installer", "extension installer",
"yii2" "yii2"
], ],
"time": "2015-03-01 06:22:44" "time": "2016-02-06T00:49:24+00:00"
}, },
{ {
"name": "yiisoft/yii2-jui", "name": "yiisoft/yii2-jui",
@ -2568,7 +2749,7 @@
"jQuery UI", "jQuery UI",
"yii2" "yii2"
], ],
"time": "2015-05-10 22:09:43" "time": "2015-05-10T22:09:43+00:00"
}, },
{ {
"name": "yiisoft/yii2-swiftmailer", "name": "yiisoft/yii2-swiftmailer",
@ -2618,7 +2799,7 @@
"swiftmailer", "swiftmailer",
"yii2" "yii2"
], ],
"time": "2015-05-10 22:12:32" "time": "2015-05-10T22:12:32+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@ -2699,7 +2880,7 @@
"faker", "faker",
"fixtures" "fixtures"
], ],
"time": "2015-05-29 06:29:14" "time": "2015-05-29T06:29:14+00:00"
}, },
{ {
"name": "phpspec/php-diff", "name": "phpspec/php-diff",
@ -2733,7 +2914,7 @@
} }
], ],
"description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).",
"time": "2013-11-01 13:02:21" "time": "2013-11-01T13:02:21+00:00"
}, },
{ {
"name": "yiisoft/yii2-codeception", "name": "yiisoft/yii2-codeception",
@ -2778,7 +2959,8 @@
"codeception", "codeception",
"yii2" "yii2"
], ],
"time": "2015-05-10 22:08:30" "abandoned": "codeception/codeception",
"time": "2015-05-10T22:08:30+00:00"
}, },
{ {
"name": "yiisoft/yii2-debug", "name": "yiisoft/yii2-debug",
@ -2825,7 +3007,7 @@
"debugger", "debugger",
"yii2" "yii2"
], ],
"time": "2015-08-06 16:14:06" "time": "2015-08-06T16:14:06+00:00"
}, },
{ {
"name": "yiisoft/yii2-faker", "name": "yiisoft/yii2-faker",
@ -2872,7 +3054,7 @@
"faker", "faker",
"yii2" "yii2"
], ],
"time": "2015-03-01 06:22:44" "time": "2015-03-01T06:22:44+00:00"
}, },
{ {
"name": "yiisoft/yii2-gii", "name": "yiisoft/yii2-gii",
@ -2925,16 +3107,18 @@
"gii", "gii",
"yii2" "yii2"
], ],
"time": "2015-05-10 22:09:31" "time": "2015-05-10T22:09:31+00:00"
} }
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {
"fxp/composer-asset-plugin": 20
},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=5.4.0" "php": ">=5.6.0"
}, },
"platform-dev": [] "platform-dev": []
} }

View File

@ -67,7 +67,7 @@ registerLocaleData(localeHu, 'hu');
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
// provider used to create fake backend // provider used to create fake backend
fakeBackendProvider // fakeBackendProvider
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -18,7 +18,7 @@ export class AuthenticationService {
// login // login
login(username: string, password:string){ login(username: string, password:string){
return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username,password}) return this.http.post<any>(Endpoints.POST_USERS_AUTHENTICATE(), {username:username,password:password})
.pipe( .pipe(
// the backend service sends an instance of the user // the backend service sends an instance of the user
// user: any (because .post<any>) // user: any (because .post<any>)

View File

@ -2,11 +2,11 @@ import {Observable} from "rxjs";
import {EventType} from "./event.service"; import {EventType} from "./event.service";
export class Endpoints { export class Endpoints {
private static contextPath = "http://localhost/api"; private static contextPath = "http://localhost:86/fitness_web";
private static baseUrl: string = Endpoints.contextPath + "/rest/web/index.php?r="; private static baseUrl: string = Endpoints.contextPath + "/customerapi/web/index.php?r=";
public static POST_USERS_AUTHENTICATE(){ public static POST_USERS_AUTHENTICATE(){
return `${this.baseUrl}/users/authenticate`; return `${this.baseUrl}user/login`;
} }
public static GET_EVENTS( ){ public static GET_EVENTS( ){

View File

@ -53,15 +53,21 @@ export interface Event {
reservationCount: number; reservationCount: number;
eventType: EventType; eventType: EventType;
reservedAt: number; reservedAt: number;
room: Room;
} }
export interface Room {
id: number;
name: string;
seat_count: number;
}
export interface EventType { export interface EventType {
id: number; id: number;
name: string; name: string;
} }
export interface DayToDisplay { export interface DayToDisplay {
date: number; date: number; //seconds
active: true; active: true;
events: Event[]; events: Event[];
} }

View File

@ -0,0 +1,18 @@
<?php
namespace customerapi\components;
class JwtValidationData extends \sizeg\jwt\JwtValidationData
{
/**
* @inheritdoc
*/
public function init()
{
$this->validationData->setIssuer('customerapi');
$this->validationData->setAudience('customer');
$this->validationData->setId('A989C57D19E2AF756BA9585AC4CFAF7974AE3D2BCA7CCA7307B39AB28CC7C2C8');
parent::init();
}
}

View File

@ -1,4 +1,8 @@
<?php <?php
use customerapi\components\JwtValidationData;
use sizeg\jwt\Jwt;
$params = array_merge( $params = array_merge(
require(__DIR__ . '/../../common/config/params.php'), require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'), require(__DIR__ . '/../../common/config/params-local.php'),
@ -38,6 +42,12 @@ return [
'errorHandler' => [ 'errorHandler' => [
'errorAction' => 'site/error', 'errorAction' => 'site/error',
], ],
'jwt' => [
'class' => Jwt::class,
'key' => 'secret',
// You have to configure ValidationData informing all claims you want to validate the token.
'jwtValidationData' => JwtValidationData::class,
],
], ],
'params' => $params, 'params' => $params,
]; ];

View File

@ -15,7 +15,7 @@ use common\models\Ticket;
use yii\web\BadRequestHttpException; use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
class CustomerController extends CustomerapiController class CustomerApiController extends RestController
{ {

View File

@ -9,20 +9,84 @@
namespace customerapi\controllers; namespace customerapi\controllers;
use common\components\Helper; use common\models\Event;
use common\models\Card; use customerapi\models\available\EventInterval;
use common\models\Ticket; use customerapi\models\available\EventAvailable;
use yii\web\BadRequestHttpException; use customerapi\models\DayToDisplay;
use yii\web\NotFoundHttpException; use DateTime;
use Exception;
class EventController extends CustomerapiController /** @noinspection PhpUnused */
class EventController extends CustomerApiController
{ {
/** @noinspection PhpUnused */
/** /**
* interface EventsAvailableResponse {
* days: DayToDisplay[];
* events: Event[];
* }
* @throws Exception
*/ */
public function actionEvent( ) public function actionAvailable()
{ {
$interval = EventInterval::createInterval();
// compose day objects
$dates = [];
for ($i = 0; $i < $interval->daysToDisplay; $i++) {
$day = clone $interval->firstDisplayDate;
$day->modify('+' . $i . ' day');
$dayToDisplay = new DayToDisplay();
$dayToDisplay->date = $day->getTimestamp();
$afterFirstActiveDay = $interval->firstActiveDate < $day || $interval->firstActiveDate == $day;
$beforeLastActiveDay = $interval->lastActiveDate > $day || $interval->lastActiveDate == $day;
$dayToDisplay->active = ($afterFirstActiveDay && $beforeLastActiveDay);
$dayToDisplay->comment = '#' . idate('W', $day->getTimestamp()) . ' - ' . $day->format('Y-m-d H:i:s');
$dayToDisplay->events = [];
$dates[] = $dayToDisplay;
}
// get events between active dates
$query = EventAvailable::find();
$query = $query->select(
[
'{{event}}.*',
// 'COUNT({{event_registration}}.id) AS reservationCount'
]);
$events = $query
->innerJoinWith('trainer')
->innerJoinWith('eventType')
->innerJoinWith('room')
->joinWith('activeEventRegistrations')
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()])
->andWhere(['<', 'event.start', (clone $interval->lastActiveDate)->modify('+1 day')->getTimestamp()])
->andWhere(['event.active' => '1'])
->all();
// set events per day
/** @var Event $event */
foreach ($events as $event) {
$eventDay = new DateTime();
$eventDay->setTimestamp($event->start);
$eventDay->setTime(0, 0);
/** @var DayToDisplay $date */
foreach ($dates as $date) {
if ($date->date === $eventDay->getTimestamp()) {
$date->events[] = $event;
break;
}
}
}
return
$this->asJson([
'interval' => $interval,
'dates' => $dates
]);
} }
} }

View File

@ -0,0 +1,67 @@
<?php
/**
* Created by IntelliJ IDEA.
* User: rocho
* Date: 2018.08.29.
* Time: 21:58
*/
namespace customerapi\controllers;
use common\manager\EventRegistrationManager;
use common\models\CardEventRegistrationForm;
use common\models\Customer;
use customerapi\models\available\EventInterval;
use customerapi\models\available\EventRegistrationAvailable;
use Throwable;
use Yii;
/** @noinspection PhpUnused */
class EventRegistrationController extends CustomerApiController
{
/** @noinspection PhpUnused */
public function actionIndex()
{
$interval = EventInterval::createInterval();
$registrations = EventRegistrationAvailable::find()
->innerJoinWith('event')
->andWhere(['and',
['>=', 'event.start', $interval->firstActiveDate->getTimestamp()],
['<', 'event.start', $interval->lastActiveDate->getTimestamp()],
['id_customer' => Yii::$app->user->getId()]
])->all();
return $this->asJson(
$registrations
);
}
/**
* @noinspection PhpUnused
* @param $idEvent
* @throws Throwable
*/
public function actionRegister($idEvent) {
/** @var Customer $customer */
$customer = Yii::$app->user->getIdentity();
$card =$customer->card;
$form = new CardEventRegistrationForm();
$form->event_id = $idEvent;
$form->card_number = $card->number;
$manager = new EventRegistrationManager();
$manager->registerCard($form);
return $form->registration;
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Created by IntelliJ IDEA.
* User: rocho
* Date: 2018.08.29.
* Time: 21:58
*/
namespace customerapi\controllers;
use common\components\HttpStatus;
use Yii;
/** @noinspection PhpUnused */
class PingController extends RestController
{
/** @noinspection PhpUnused */
public function actionPing( )
{
Yii::$app->response->setStatusCode( HttpStatus::NO_CONTENT );
}
}

View File

@ -3,44 +3,58 @@
namespace customerapi\controllers; namespace customerapi\controllers;
use common\components\Helper;
use common\models\Card;
use common\models\Customer; use common\models\Customer;
use yii\filters\auth\HttpBasicAuth; use Exception;
use Lcobucci\JWT\Token;
use sizeg\jwt\JwtHttpBearerAuth;
use Yii;
use yii\filters\auth\AuthMethod;
use yii\rest\Controller;
class RestController extends \yii\web\Controller class RestController extends Controller
{ {
public function behaviors() public function behaviors()
{ {
$behaviors = parent::behaviors(); $behaviors = parent::behaviors();
$behaviors['authenticator'] = [ $behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(), 'class' => JwtHttpBearerAuth::class,
'auth' => [$this, 'auth'] 'auth' => [$this, 'auth'],
'optional' => $this->getOptionalActions(),
]; ];
return $behaviors; return $behaviors;
} }
public function auth($username, $password) /**
* This method will check the token
* @param Token $token
* @return Customer|null
*/
public function auth($token)
{ {
if ( !isset($token ) ) {
return null;
}
try { try {
// $query = Card::find(); $uid = (string) $token->getClaim('uid');
// Card::addCardNumberCondition($query, Helper::fixAsciiChars($username)); $customer = Customer::findOne(['id_customer' => $uid]);
// $card = $query->one();
$customer = Customer::findOne(['email' => $username]);
if (isset($customer)) { if (isset($customer)) {
if ($customer->validatePassword($password)) { \Yii::$app->user->setIdentity($customer);
return $customer; return $customer;
}
} }
} catch (\Exception $e) { } catch (Exception $e) {
\Yii::error("Failed to load user: " . $e->getMessage()); Yii::error('Failed to load customer: ' . $e->getMessage());
} }
return null; return null;
} }
/**
* @see AuthMethod::$optional
* @return array
*/
protected function getOptionalActions(){
return [];
}
} }

View File

@ -8,21 +8,61 @@
namespace customerapi\controllers; namespace customerapi\controllers;
use common\models\Customer;
use customerapi\models\LoginForm;
use sizeg\jwt\Jwt;
use sizeg\jwt\JwtHttpBearerAuth;
use Yii;
use common\components\Helper; /** @noinspection PhpUnused */
use common\models\Card;
use common\models\Ticket;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;
class UserController extends RestController class UserController extends RestController
{ {
/**
*/ /** @noinspection PhpUnused */
public function actionLogin( ) public function actionLogin( )
{ {
\Yii::$app->response->setStatusCode(204);
$form = new LoginForm();
$form->load(\Yii::$app->request->post( ), '');
if ( $form->validate() ){
/** @var Jwt $jwt */
$jwt = Yii::$app->jwt;
$signer = $jwt->getSigner('HS256');
$key = $jwt->getKey();
$time = time();
// Adoption for lcobucci/jwt ^4.0 version
$token = $jwt->getBuilder()
->issuedBy('customerapi')// Configures the issuer (iss claim)
->permittedFor('customer')// Configures the audience (aud claim)
->identifiedBy('A989C57D19E2AF756BA9585AC4CFAF7974AE3D2BCA7CCA7307B39AB28CC7C2C8', true)// Configures the id (jti claim), replicating as a header item
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim)
->withClaim('uid', $form->getCustomer()->getId())// Configures a new claim, called "uid"
->getToken($signer, $key); // Retrieves the generated token
return $this->asJson([
'token' => (string)$token,
]);
} else {
return $this->asJson(
[
'errors' => $form->getErrors()
]
);
}
}
protected function getOptionalActions()
{
return ['login'];
} }

View File

@ -0,0 +1,13 @@
<?php
namespace customerapi\models;
class DayToDisplay
{
public $date;//: number; //seconds
public $active;//: true;
public $events;//: Event[];
public $comment;
}

View File

@ -0,0 +1,21 @@
<?php
namespace customerapi\models;
use yii\base\Component;
use yii\base\Model;
class EventView extends Component
{
public $id;//: number;
public $name;//: string;
public $start;//: number;
public $end;//: number;
public $trainer;//?: Trainer;
public $seatCount;//: number;
public $reservationCount;//: number;
public $eventType;//: EventType;
public $reservedAt;//: number;
}

View File

@ -0,0 +1,70 @@
<?php
namespace customerapi\models;
use common\models\Customer;
use Yii;
use yii\base\Model;
/**
* Login form
*/
class LoginForm extends Model
{
public $username;
public $password;
public $customer;
/**
* @inheritdoc
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
public function attributeLabels(){
return [
'username' =>Yii::t('common/site', 'Username'),
'password' =>Yii::t('common/site', 'Password'),
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
* @throws \yii\base\InvalidConfigException
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
/** @var \common\models\Customer $user */
$customer = $this->getCustomer();
if (!$customer || !$customer->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Finds user by [[username]]
*
* @return Customer|null
*/
public function getCustomer()
{
if ( $this->customer === null ){
$this->customer = Customer::findIdentity( $this->username );
}
return $this->customer;
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace customerapi\models\available;
use common\models\Event;
use common\models\EventType;
class EventAvailable extends Event
{
public $reservationCount;
protected function getTrainerClass()
{
// override trainer class to have more control
// about json fields
return TrainerAvailable::class;
}
protected function getEventTypeClass()
{
return EventTypeAvailable::class;
}
protected function getRoomClass()
{
return RoomAvailable::class;
}
function fields()
{
$fields = [
"id" => "id",
"start" => "start",
"end" => "end",
"seat_count" => "seat_count",
"active" => "active",
// "reservationCount" => "reservationCount"
];
$fields['trainer'] = 'trainer';
$fields['eventType'] = 'eventType';
$fields['room'] = 'room';
return $fields;
}
function extraFields()
{
$extra= parent::extraFields();
$extra[] = 'trainer';
return $extra;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace customerapi\models\available;
use DateTime;
/**
* Class DateIntervalHelper
* @package customerapi\models\available
* @property \DateTime $firstActiveDate
* @property \DateTime $lastActiveDate
* @property \DateTime $firstDisplayDate
* @property \DateTime $lastDisplayDate
*/
class EventInterval
{
public $countOfActiveDays = 14;
public $daysToDisplay = 21;
public $firstActiveDate;
public $lastActiveDate;
public $firstDisplayDate;
public $lastDisplayDate;
private function __construct()
{
$firstActiveDay = new DateTime();
$firstActiveDay->setTime(0, 0);
$this->firstActiveDate = $firstActiveDay;
$lastActiveDay = new DateTime();
$lastActiveDay->setTime(0, 0);
$lastActiveDay->modify('+' . $this->countOfActiveDays . ' day');
$this->lastActiveDate = $lastActiveDay;
$firstDisplayDate = new DateTime();
$firstDisplayDate->modify('this week');
$firstDisplayDate->setTime(0, 0);
$this->firstDisplayDate = $firstDisplayDate;
$lastDisplayDate = clone $firstDisplayDate;
$lastDisplayDate->setTime(0, 0);
$lastDisplayDate->modify('+' . $this->daysToDisplay . ' day');
$this->lastDisplayDate = $lastDisplayDate;
}
public static function createInterval(){
return new EventInterval();
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace customerapi\models\available;
use common\models\EventRegistration;
class EventRegistrationAvailable extends EventRegistration
{
}

View File

@ -0,0 +1,20 @@
<?php
namespace customerapi\models\available;
use common\models\EventType;
class EventTypeAvailable extends EventType
{
function fields()
{
return [
'id' => 'id',
'name' => 'name'
];
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace customerapi\models\available;
use common\models\Room;
class RoomAvailable extends Room
{
function fields()
{
return [
'id' => 'id',
'name' => 'name',
'seat_count' => 'seat_count'
];
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace customerapi\models\available;
use common\models\Trainer;
class TrainerAvailable extends Trainer
{
public function fields()
{
return [
'id' => 'id',
'name' => 'name'
];
}
}

View File

23
doc/upgrade.txt Normal file
View File

@ -0,0 +1,23 @@
composer self-update
## composer --version
## Do not run Composer as root/super user! See https://getcomposer.org/root for details
## Composer version 1.9.0 2019-08-02 20:55:32
composer config -g github-oauth.github.com 4fe4faf52ce29b298d02c6473a1ee7e10047ed7c
#token: 4fe4faf52ce29b298d02c6473a1ee7e10047ed7c
composer require "fxp/composer-asset-plugin:^1.1.3"
composer require "fxp/composer-asset-plugin:dev-master"
# composer require "yiisoft/yii2":"2.0.7"
# sometimes it works only, if we first update to this version and then to the higher version
composer require "yiisoft/yii2":"2.0.5"
composer require "yiisoft/yii2:~2.0.10" --update-with-dependencies