+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+.
diff --git a/src/Bundle/ChillEvent/README.md b/src/Bundle/ChillEvent/README.md
new file mode 100644
index 000000000..2aad96db5
--- /dev/null
+++ b/src/Bundle/ChillEvent/README.md
@@ -0,0 +1,16 @@
+Chill Event Bundle
+====================
+
+This bundle extend [chill software](https://www.chill.social). This bundle allow to define event and participation to those events.
+
+Documentation & installation
+============================
+
+This bundle can be installed with the Chill software.
+
+Read documentation here : http://chill.readthedocs.org
+
+Issues and bug tracking
+=======================
+
+The issues tracker is here : https://git.framasoft.org/Chill-project/Chill-Event/issues
diff --git a/src/Bundle/ChillEvent/Resources/config/doctrine/Event.orm.yml b/src/Bundle/ChillEvent/Resources/config/doctrine/Event.orm.yml
new file mode 100644
index 000000000..eb02041e4
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/doctrine/Event.orm.yml
@@ -0,0 +1,27 @@
+Chill\EventBundle\Entity\Event:
+ type: entity
+ table: chill_event_event
+ id:
+ id:
+ type: integer
+ id: true
+ generator:
+ strategy: AUTO
+ fields:
+ name:
+ type: string
+ length: '150'
+ date:
+ type: date
+ oneToMany:
+ participations:
+ targetEntity: Chill\EventBundle\Entity\Participation
+ mappedBy: event
+ manyToOne:
+ center:
+ targetEntity: Chill\MainBundle\Entity\Center
+ type:
+ targetEntity: Chill\EventBundle\Entity\EventType
+ circle:
+ targetEntity: Chill\MainBundle\Entity\Scope
+ lifecycleCallbacks: { }
diff --git a/src/Bundle/ChillEvent/Resources/config/doctrine/EventType.orm.yml b/src/Bundle/ChillEvent/Resources/config/doctrine/EventType.orm.yml
new file mode 100644
index 000000000..dcfab3ba6
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/doctrine/EventType.orm.yml
@@ -0,0 +1,22 @@
+Chill\EventBundle\Entity\EventType:
+ type: entity
+ table: chill_event_event_type
+ id:
+ id:
+ type: integer
+ id: true
+ generator:
+ strategy: AUTO
+ fields:
+ name:
+ type: json_array
+ active:
+ type: boolean
+ oneToMany:
+ roles:
+ targetEntity: Chill\EventBundle\Entity\Role
+ mappedBy: type
+ statuses:
+ targetEntity: Chill\EventBundle\Entity\Status
+ mappedBy: type
+ lifecycleCallbacks: { }
diff --git a/src/Bundle/ChillEvent/Resources/config/doctrine/Participation.orm.yml b/src/Bundle/ChillEvent/Resources/config/doctrine/Participation.orm.yml
new file mode 100644
index 000000000..24858afc4
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/doctrine/Participation.orm.yml
@@ -0,0 +1,23 @@
+Chill\EventBundle\Entity\Participation:
+ type: entity
+ table: chill_event_participation
+ id:
+ id:
+ type: integer
+ id: true
+ generator:
+ strategy: AUTO
+ fields:
+ lastUpdate:
+ type: datetime
+ manyToOne:
+ event:
+ targetEntity: Chill\EventBundle\Entity\Event
+ inversedBy: participations
+ person:
+ targetEntity: Chill\PersonBundle\Entity\Person
+ role:
+ targetEntity: Chill\EventBundle\Entity\Role
+ status:
+ targetEntity: Chill\EventBundle\Entity\Status
+ lifecycleCallbacks: { }
diff --git a/src/Bundle/ChillEvent/Resources/config/doctrine/Role.orm.yml b/src/Bundle/ChillEvent/Resources/config/doctrine/Role.orm.yml
new file mode 100644
index 000000000..b6a1ae677
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/doctrine/Role.orm.yml
@@ -0,0 +1,19 @@
+Chill\EventBundle\Entity\Role:
+ type: entity
+ table: chill_event_role
+ id:
+ id:
+ type: integer
+ id: true
+ generator:
+ strategy: AUTO
+ fields:
+ name:
+ type: json_array
+ active:
+ type: boolean
+ manyToOne:
+ type:
+ targetEntity: Chill\EventBundle\Entity\EventType
+ inversedBy: roles
+ lifecycleCallbacks: { }
diff --git a/src/Bundle/ChillEvent/Resources/config/doctrine/Status.orm.yml b/src/Bundle/ChillEvent/Resources/config/doctrine/Status.orm.yml
new file mode 100644
index 000000000..f1567f8f0
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/doctrine/Status.orm.yml
@@ -0,0 +1,19 @@
+Chill\EventBundle\Entity\Status:
+ type: entity
+ table: chill_event_status
+ id:
+ id:
+ type: integer
+ id: true
+ generator:
+ strategy: AUTO
+ fields:
+ name:
+ type: json_array
+ active:
+ type: boolean
+ manyToOne:
+ type:
+ targetEntity: Chill\EventBundle\Entity\EventType
+ inversedBy: statuses
+ lifecycleCallbacks: { }
diff --git a/src/Bundle/ChillEvent/Resources/config/routing.yml b/src/Bundle/ChillEvent/Resources/config/routing.yml
new file mode 100644
index 000000000..c8be2882e
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing.yml
@@ -0,0 +1,19 @@
+chill_event_event:
+ resource: "@ChillEventBundle/Resources/config/routing/event.yml"
+ prefix: /{_locale}/event/event
+
+chill_event_fr_admin_event_status:
+ resource: "@ChillEventBundle/Resources/config/routing/status.yml"
+ prefix: /{_locale}/admin/event/status
+
+chill_event_admin_role:
+ resource: "@ChillEventBundle/Resources/config/routing/role.yml"
+ prefix: /{_locale}/admin/event/role
+
+chill_event_admin_event_type:
+ resource: "@ChillEventBundle/Resources/config/routing/eventtype.yml"
+ prefix: /{_locale}/admin/event/event_type
+
+chill_event_participation:
+ resource: "@ChillEventBundle/Resources/config/routing/participation.yml"
+ prefix: /{_locale}/event/participation
diff --git a/src/Bundle/ChillEvent/Resources/config/routing/event.yml b/src/Bundle/ChillEvent/Resources/config/routing/event.yml
new file mode 100644
index 000000000..256850e5c
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing/event.yml
@@ -0,0 +1,37 @@
+chill_event_list_most_recent:
+ path: most_recent
+ defaults: { _controller: "ChillEventBundle:Event:mostRecentIndex" }
+ options:
+ menus:
+ section:
+ order: 90
+ label: Events
+ icons: [calendar]
+
+chill_event__event_show:
+ path: /{event_id}/show
+ defaults: { _controller: "ChillEventBundle:Event:show" }
+
+chill_event__event_new:
+ path: /new
+ defaults: { _controller: "ChillEventBundle:Event:new" }
+ options:
+ menus:
+ section:
+ order: 11
+ label: Add an event
+ icons: [plus, calendar-o]
+
+chill_event__event_create:
+ path: /create
+ defaults: { _controller: "ChillEventBundle:Event:create" }
+ methods: POST
+
+chill_event__event_edit:
+ path: /{event_id}/edit
+ defaults: { _controller: "ChillEventBundle:Event:edit" }
+
+chill_event__event_update:
+ path: /{event_id}/update
+ defaults: { _controller: "ChillEventBundle:Event:update" }
+ methods: [POST, PUT]
diff --git a/src/Bundle/ChillEvent/Resources/config/routing/eventtype.yml b/src/Bundle/ChillEvent/Resources/config/routing/eventtype.yml
new file mode 100644
index 000000000..305c27af8
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing/eventtype.yml
@@ -0,0 +1,30 @@
+chill_eventtype_admin:
+ path: /
+ defaults: { _controller: "ChillEventBundle:EventType:index" }
+
+chill_eventtype_admin_show:
+ path: /{id}/show
+ defaults: { _controller: "ChillEventBundle:EventType:show" }
+
+chill_eventtype_admin_new:
+ path: /new
+ defaults: { _controller: "ChillEventBundle:EventType:new" }
+
+chill_eventtype_admin_create:
+ path: /create
+ defaults: { _controller: "ChillEventBundle:EventType:create" }
+ methods: POST
+
+chill_eventtype_admin_edit:
+ path: /{id}/edit
+ defaults: { _controller: "ChillEventBundle:EventType:edit" }
+
+chill_eventtype_admin_update:
+ path: /{id}/update
+ defaults: { _controller: "ChillEventBundle:EventType:update" }
+ methods: [POST, PUT]
+
+chill_eventtype_admin_delete:
+ path: /{id}/delete
+ defaults: { _controller: "ChillEventBundle:EventType:delete" }
+ methods: [POST, DELETE]
diff --git a/src/Bundle/ChillEvent/Resources/config/routing/participation.yml b/src/Bundle/ChillEvent/Resources/config/routing/participation.yml
new file mode 100644
index 000000000..bbb727382
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing/participation.yml
@@ -0,0 +1,25 @@
+chill_event_participation_new:
+ path: /new
+ defaults: { _controller: ChillEventBundle:Participation:new }
+
+chill_event_participation_create:
+ path: /create
+ defaults: { _controller: ChillEventBundle:Participation:create }
+
+chill_event_participation_edit:
+ path: /{participation_id}/edit
+ defaults: { _controller: ChillEventBundle:Participation:edit }
+
+chill_event_participation_update:
+ path: /{participation_id}/update
+ defaults: { _controller: ChillEventBundle:Participation:update }
+ methods: [POST]
+
+chill_event_participation_edit_multiple:
+ path: /{event_id}/edit_multiple
+ defaults: { _controller: ChillEventBundle:Participation:editMultiple }
+
+chill_event_participation_update_multiple:
+ path: /{event_id}/update_multiple
+ defaults: { _controller: ChillEventBundle:Participation:updateMultiple }
+ methods: [POST]
diff --git a/src/Bundle/ChillEvent/Resources/config/routing/role.yml b/src/Bundle/ChillEvent/Resources/config/routing/role.yml
new file mode 100644
index 000000000..bfc51216d
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing/role.yml
@@ -0,0 +1,30 @@
+chill_event_admin_role:
+ path: /
+ defaults: { _controller: "ChillEventBundle:Role:index" }
+
+chill_event_admin_role_show:
+ path: /{id}/show
+ defaults: { _controller: "ChillEventBundle:Role:show" }
+
+chill_event_admin_role_new:
+ path: /new
+ defaults: { _controller: "ChillEventBundle:Role:new" }
+
+chill_event_admin_role_create:
+ path: /create
+ defaults: { _controller: "ChillEventBundle:Role:create" }
+ methods: POST
+
+chill_event_admin_role_edit:
+ path: /{id}/edit
+ defaults: { _controller: "ChillEventBundle:Role:edit" }
+
+chill_event_admin_role_update:
+ path: /{id}/update
+ defaults: { _controller: "ChillEventBundle:Role:update" }
+ methods: [POST, PUT]
+
+chill_event_admin_role_delete:
+ path: /{id}/delete
+ defaults: { _controller: "ChillEventBundle:Role:delete" }
+ methods: [POST, DELETE]
diff --git a/src/Bundle/ChillEvent/Resources/config/routing/status.yml b/src/Bundle/ChillEvent/Resources/config/routing/status.yml
new file mode 100644
index 000000000..383a704ff
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/routing/status.yml
@@ -0,0 +1,30 @@
+chill_event_admin_status:
+ path: /
+ defaults: { _controller: "ChillEventBundle:Status:index" }
+
+chill_event_admin_status_show:
+ path: /{id}/show
+ defaults: { _controller: "ChillEventBundle:Status:show" }
+
+chill_event_admin_status_new:
+ path: /new
+ defaults: { _controller: "ChillEventBundle:Status:new" }
+
+chill_event_admin_status_create:
+ path: /create
+ defaults: { _controller: "ChillEventBundle:Status:create" }
+ methods: POST
+
+chill_event_admin_status_edit:
+ path: /{id}/edit
+ defaults: { _controller: "ChillEventBundle:Status:edit" }
+
+chill_event_admin_status_update:
+ path: /{id}/update
+ defaults: { _controller: "ChillEventBundle:Status:update" }
+ methods: [POST, PUT]
+
+chill_event_admin_status_delete:
+ path: /{id}/delete
+ defaults: { _controller: "ChillEventBundle:Status:delete" }
+ methods: [POST, DELETE]
diff --git a/src/Bundle/ChillEvent/Resources/config/services/authorization.yml b/src/Bundle/ChillEvent/Resources/config/services/authorization.yml
new file mode 100644
index 000000000..d44f1e9d9
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/services/authorization.yml
@@ -0,0 +1,16 @@
+services:
+ chill_event.event_voter:
+ class: Chill\EventBundle\Security\Authorization\EventVoter
+ arguments:
+ - "@chill.main.security.authorization.helper"
+ tags:
+ - { name: chill.role }
+ - { name: security.voter }
+
+ chill_event.event_participation:
+ class: Chill\EventBundle\Security\Authorization\ParticipationVoter
+ arguments:
+ - "@chill.main.security.authorization.helper"
+ tags:
+ - { name: chill.role }
+ - { name: security.voter }
diff --git a/src/Bundle/ChillEvent/Resources/config/services/forms.yml b/src/Bundle/ChillEvent/Resources/config/services/forms.yml
new file mode 100644
index 000000000..90981d31b
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/services/forms.yml
@@ -0,0 +1,48 @@
+services:
+ chill.event.form.type.pick_event_type:
+ class: Chill\EventBundle\Form\Type\PickEventType
+ arguments:
+ - "@chill.main.helper.translatable_string"
+ tags:
+ - { name: form.type }
+
+ chill.event.form.event_type_test:
+ class: Chill\EventBundle\Form\EventType
+ arguments:
+ - "@security.token_storage"
+ - "@chill.main.security.authorization.helper"
+ - "@chill.main.helper.translatable_string"
+ tags:
+ - { name: form.type }
+
+ chill.event.form.participation_type:
+ class: Chill\EventBundle\Form\ParticipationType
+ arguments:
+ - "@chill.main.helper.translatable_string"
+ tags:
+ - { name: form.type }
+
+ chill.event.form.pick_role_type:
+ class: Chill\EventBundle\Form\Type\PickRoleType
+ arguments:
+ - "@chill.main.helper.translatable_string"
+ - "@translator"
+ - "@chill_event.repository.role"
+ tags:
+ - { name: form.type }
+
+ chill.event.form.pick_status_type:
+ class: Chill\EventBundle\Form\Type\PickStatusType
+ arguments:
+ - "@chill.main.helper.translatable_string"
+ - "@translator"
+ - "@chill_event.repository.status"
+ tags:
+ - { name: form.type }
+
+ chill.event.form.role_type:
+ class: Chill\EventBundle\Form\RoleType
+ arguments:
+ - "@chill.main.helper.translatable_string"
+ tags:
+ - { name: form.type }
diff --git a/src/Bundle/ChillEvent/Resources/config/services/repositories.yml b/src/Bundle/ChillEvent/Resources/config/services/repositories.yml
new file mode 100644
index 000000000..d27130bcd
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/services/repositories.yml
@@ -0,0 +1,18 @@
+services:
+ chill_event.repository.event:
+ class: Doctrine\ORM\EntityRepository
+ factory: ['@doctrine.orm.entity_manager', getRepository]
+ arguments:
+ - 'Chill\EventBundle\Entity\Event'
+
+ chill_event.repository.role:
+ class: Doctrine\ORM\EntityRepository
+ factory: ['@doctrine.orm.entity_manager', getRepository]
+ arguments:
+ - 'Chill\EventBundle\Entity\Role'
+
+ chill_event.repository.status:
+ class: Doctrine\ORM\EntityRepository
+ factory: ['@doctrine.orm.entity_manager', getRepository]
+ arguments:
+ - 'Chill\EventBundle\Entity\Status'
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/config/services/search.yml b/src/Bundle/ChillEvent/Resources/config/services/search.yml
new file mode 100644
index 000000000..2df3db26f
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/services/search.yml
@@ -0,0 +1,12 @@
+services:
+ chill_event.search_events:
+ class: Chill\EventBundle\Search\EventSearch
+ arguments:
+ - "@security.token_storage"
+ - "@chill_event.repository.event"
+ - "@chill.main.security.authorization.helper"
+ - "@templating"
+ - "@chill_main.paginator_factory"
+ tags:
+ - { name: chill.search, alias: 'event_regular' }
+
diff --git a/src/Bundle/ChillEvent/Resources/config/validation.yml b/src/Bundle/ChillEvent/Resources/config/validation.yml
new file mode 100644
index 000000000..d6a12b418
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/config/validation.yml
@@ -0,0 +1,26 @@
+Chill\EventBundle\Entity\Participation:
+ properties:
+ event:
+ - NotNull: ~
+ status:
+ - NotNull: ~
+ person:
+ - NotNull: ~
+ constraints:
+ - Callback: [isConsistent]
+
+
+Chill\EventBundle\Entity\Event:
+ properties:
+ name:
+ - Length:
+ min: 3
+ max: 75
+ minMessage: The event name must have at least {{ limit }} characters.
+ maxMessage: The event name must have maximum {{ limit }} characters.
+ type:
+ - NotNull: ~
+ circle:
+ - NotNull: ~
+ center:
+ - NotNull: ~
diff --git a/src/Bundle/ChillEvent/Resources/migrations/Version20160318111334.php b/src/Bundle/ChillEvent/Resources/migrations/Version20160318111334.php
new file mode 100644
index 000000000..df23eaab1
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/migrations/Version20160318111334.php
@@ -0,0 +1,141 @@
+abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
+
+ $this->addSql('CREATE SEQUENCE chill_event_event_type_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
+ $this->addSql('CREATE SEQUENCE chill_event_role_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
+ $this->addSql('CREATE SEQUENCE chill_event_status_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
+ $this->addSql('CREATE SEQUENCE chill_event_event_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
+ $this->addSql('CREATE SEQUENCE chill_event_participation_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
+ $this->addSql('CREATE TABLE chill_event_event_type ('
+ . 'id INT NOT NULL, name JSON NOT NULL, '
+ . 'active BOOLEAN NOT NULL, PRIMARY KEY(id))');
+ $this->addSql('CREATE TABLE chill_event_role ('
+ . 'id INT NOT NULL, '
+ . 'type_id INT DEFAULT NULL, '
+ . 'name JSON NOT NULL, '
+ . 'active BOOLEAN NOT NULL, '
+ . 'PRIMARY KEY(id))');
+ $this->addSql('CREATE INDEX IDX_AA714E54C54C8C93 ON chill_event_role (type_id)');
+ $this->addSql('CREATE TABLE chill_event_status (id INT NOT NULL, '
+ . 'type_id INT DEFAULT NULL, '
+ . 'name JSON NOT NULL, '
+ . 'active BOOLEAN NOT NULL, '
+ . 'PRIMARY KEY(id))');
+ $this->addSql('CREATE INDEX IDX_A6CC85D0C54C8C93 ON chill_event_status (type_id)');
+ $this->addSql('CREATE TABLE chill_event_event ('
+ . 'id INT NOT NULL, '
+ . 'name VARCHAR(150) NOT NULL, '
+ . 'date DATE NOT NULL, '
+ . 'center_id INT DEFAULT NULL, '
+ . 'type_id INT DEFAULT NULL, '
+ . 'circle_id INT DEFAULT NULL, '
+ . 'PRIMARY KEY(id))');
+ $this->addSql('CREATE TABLE chill_event_participation ('
+ . 'id INT NOT NULL, '
+ . 'event_id INT DEFAULT NULL, '
+ . 'person_id INT DEFAULT NULL, '
+ . 'role_id INT DEFAULT NULL, '
+ . 'status_id INT DEFAULT NULL, '
+ . 'lastUpdate TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, '
+ . 'PRIMARY KEY(id))');
+ $this->addSql('CREATE INDEX IDX_4E7768AC71F7E88B ON chill_event_participation (event_id)');
+ $this->addSql('CREATE INDEX IDX_4E7768AC217BBB47 ON chill_event_participation (person_id)');
+ $this->addSql('CREATE INDEX IDX_4E7768ACD60322AC ON chill_event_participation (role_id)');
+ $this->addSql('CREATE INDEX IDX_4E7768AC6BF700BD ON chill_event_participation (status_id)');
+ $this->addSql('CREATE INDEX IDX_FA320FC85932F377 ON chill_event_event (center_id)');
+ $this->addSql('CREATE INDEX IDX_FA320FC8C54C8C93 ON chill_event_event (type_id)');
+ $this->addSql('CREATE INDEX IDX_FA320FC870EE2FF6 ON chill_event_event (circle_id)');
+
+ $this->addSql('ALTER TABLE chill_event_event '
+ . 'ADD CONSTRAINT FK_FA320FC85932F377 FOREIGN KEY (center_id) '
+ . 'REFERENCES centers (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_event '
+ . 'ADD CONSTRAINT FK_FA320FC870EE2FF6 FOREIGN KEY (circle_id) '
+ . 'REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_event '
+ . 'ADD CONSTRAINT FK_FA320FC8C54C8C93 FOREIGN KEY (type_id) '
+ . 'REFERENCES chill_event_event_type (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_role '
+ . 'ADD CONSTRAINT FK_AA714E54C54C8C93 FOREIGN KEY (type_id) '
+ . 'REFERENCES chill_event_event_type (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_status '
+ . 'ADD CONSTRAINT FK_A6CC85D0C54C8C93 '
+ . 'FOREIGN KEY (type_id) '
+ . 'REFERENCES chill_event_event_type (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_participation '
+ . 'ADD CONSTRAINT FK_4E7768AC71F7E88B '
+ . 'FOREIGN KEY (event_id) '
+ . 'REFERENCES chill_event_event (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_participation '
+ . 'ADD CONSTRAINT FK_4E7768AC217BBB47 '
+ . 'FOREIGN KEY (person_id) '
+ . 'REFERENCES Person (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_participation '
+ . 'ADD CONSTRAINT FK_4E7768ACD60322AC '
+ . 'FOREIGN KEY (role_id) '
+ . 'REFERENCES chill_event_role (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+ $this->addSql('ALTER TABLE chill_event_participation '
+ . 'ADD CONSTRAINT FK_4E7768AC6BF700BD '
+ . 'FOREIGN KEY (status_id) '
+ . 'REFERENCES chill_event_status (id) '
+ . 'NOT DEFERRABLE INITIALLY IMMEDIATE');
+
+ }
+
+ /**
+ * @param Schema $schema
+ */
+ public function down(Schema $schema)
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
+
+ $this->addSql('ALTER TABLE chill_event_role DROP CONSTRAINT FK_AA714E54C54C8C93');
+ $this->addSql('ALTER TABLE chill_event_status DROP CONSTRAINT FK_A6CC85D0C54C8C93');
+ $this->addSql('ALTER TABLE chill_event_participation DROP CONSTRAINT FK_4E7768ACD60322AC');
+ $this->addSql('ALTER TABLE chill_event_participation DROP CONSTRAINT FK_4E7768AC6BF700BD');
+ $this->addSql('ALTER TABLE chill_event_participation DROP CONSTRAINT FK_4E7768AC71F7E88B');
+ // drop center_id constraint
+ $this->addSql('ALTER TABLE chill_event_event DROP CONSTRAINT FK_FA320FC85932F377');
+ // drop type_id constraint
+ $this->addSql('ALTER TABLE chill_event_event DROP CONSTRAINT FK_FA320FC8C54C8C93');
+ // drop circle_id constraint
+ $this->addSql('ALTER TABLE chill_event_event DROP CONSTRAINT FK_FA320FC870EE2FF6');
+
+ $this->addSql('DROP SEQUENCE chill_event_event_type_id_seq CASCADE');
+ $this->addSql('DROP SEQUENCE chill_event_role_id_seq CASCADE');
+ $this->addSql('DROP SEQUENCE chill_event_status_id_seq CASCADE');
+ $this->addSql('DROP SEQUENCE chill_event_event_id_seq CASCADE');
+ $this->addSql('DROP SEQUENCE chill_event_participation_id_seq CASCADE');
+ $this->addSql('DROP TABLE chill_event_event_type');
+ $this->addSql('DROP TABLE chill_event_role');
+ $this->addSql('DROP TABLE chill_event_status');
+ $this->addSql('DROP TABLE chill_event_event');
+ $this->addSql('DROP TABLE chill_event_participation');
+
+ }
+}
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/AppKernel.php b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/AppKernel.php
new file mode 100644
index 000000000..366c1e6a0
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/AppKernel.php
@@ -0,0 +1,46 @@
+load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
+ }
+
+ /**
+ * @return string
+ */
+ public function getCacheDir()
+ {
+ return sys_get_temp_dir().'/ChillEventBundle/cache';
+ }
+
+ /**
+ * @return string
+ */
+ public function getLogDir()
+ {
+ return sys_get_temp_dir().'/ChillEventBundle/logs';
+ }
+}
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config.yml b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config.yml
new file mode 100644
index 000000000..cf6bb3108
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config.yml
@@ -0,0 +1,43 @@
+imports:
+ - { resource: parameters.yml }
+
+framework:
+ secret: Not very secret
+ router: { resource: "%kernel.root_dir%/config/routing.yml" }
+ form: true
+ csrf_protection: true
+ session: ~
+ default_locale: fr
+ translator: { fallback: fr }
+ profiler: { only_exceptions: false }
+ templating:
+ engines: ['twig']
+
+# Doctrine Configuration
+doctrine:
+ dbal:
+ driver: pdo_pgsql
+ host: "%database_host%"
+ port: "%database_port%"
+ dbname: "%database_name%"
+ user: "%database_user%"
+ password: "%database_password%"
+ charset: UTF8
+ mapping_types:
+ jsonb: json_array
+
+ orm:
+ auto_generate_proxy_classes: "%kernel.debug%"
+ auto_mapping: true
+
+# Assetic Configuration
+assetic:
+ debug: "%kernel.debug%"
+ use_controller: false
+ bundles: [ ]
+ #java: /usr/bin/java
+ filters:
+ cssrewrite: ~
+
+chill_main:
+ available_languages: [fr, en]
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config_test.yml b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config_test.yml
new file mode 100644
index 000000000..b4f6d786a
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/config_test.yml
@@ -0,0 +1,52 @@
+imports:
+ - { resource: config.yml }
+
+framework:
+ test: ~
+ session:
+ storage_id: session.storage.filesystem
+
+security:
+ role_hierarchy:
+ CHILL_MASTER_ROLE: [CHILL_INHERITED_ROLE_1]
+ providers:
+ chain_provider:
+ chain :
+ providers: [in_memory, users]
+ in_memory:
+ memory:
+ users:
+ admin: { password: "password", roles: 'ROLE_ADMIN' }
+ users:
+ entity:
+ class: Chill\MainBundle\Entity\User
+ property: username
+
+ encoders:
+ Chill\MainBundle\Entity\User:
+ algorithm: bcrypt
+ Symfony\Component\Security\Core\User\User:
+ algorithm: plaintext
+
+ firewalls:
+ dev:
+ pattern: ^/(_(profiler|wdt)|css|images|js)/
+ security: false
+
+
+
+ default:
+ anonymous: ~
+ http_basic: ~
+ form_login:
+ csrf_parameter: _csrf_token
+ csrf_token_id: authenticate
+ csrf_provider: form.csrf_provider
+
+ logout: ~
+
+
+ access_control:
+ - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
+ - { path: ^/[a-z]*/admin, roles: ROLE_ADMIN }
+ - { path: ^/, roles: ROLE_USER }
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.gitlab-ci.yml b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.gitlab-ci.yml
new file mode 100644
index 000000000..c4e63ef76
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.gitlab-ci.yml
@@ -0,0 +1,11 @@
+parameters:
+ database_host: chill__database
+ database_port: 5432
+ database_name: postgres
+ database_user: postgres
+ database_password: postgres
+ locale: fr
+ secret: ThisTokenIsNotSoSecretChangeIt
+ debug_toolbar: true
+ debug_redirects: false
+ use_assetic_controller: true
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml
new file mode 100644
index 000000000..d92cc2318
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml
@@ -0,0 +1,11 @@
+parameters:
+ database_host: 127.0.0.1
+ database_port: 5435
+ database_name: postgres
+ database_user: postgres
+ database_password: postgres
+ locale: fr
+ secret: ThisTokenIsNotSoSecretChangeIt
+ debug_toolbar: true
+ debug_redirects: false
+ use_assetic_controller: true
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml.dist b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml.dist
new file mode 100644
index 000000000..38fab7fd2
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/parameters.yml.dist
@@ -0,0 +1,11 @@
+parameters:
+ database_host: 127.0.0.1
+ database_port: 5435
+ database_name: chill
+ database_user: chill
+ database_password: chill
+ locale: fr
+ secret: ThisTokenIsNotSoSecretChangeIt
+ debug_toolbar: true
+ debug_redirects: false
+ use_assetic_controller: true
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/routing.yml b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/routing.yml
new file mode 100644
index 000000000..802d3a1c8
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/config/routing.yml
@@ -0,0 +1,4 @@
+#load routes for chil bundles
+chill_routes:
+ resource: .
+ type: chill_routes
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/test/Fixtures/App/console b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/console
new file mode 100644
index 000000000..4ee9cfb33
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/Fixtures/App/console
@@ -0,0 +1,27 @@
+#!/usr/bin/env php
+getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'test');
+$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
+
+if ($debug) {
+ Debug::enable();
+}
+
+$kernel = new AppKernel($env, $debug);
+$application = new Application($kernel);
+$application->run($input);
diff --git a/src/Bundle/ChillEvent/Resources/test/bootstrap.php b/src/Bundle/ChillEvent/Resources/test/bootstrap.php
new file mode 100644
index 000000000..0279b4ee6
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/test/bootstrap.php
@@ -0,0 +1,8 @@
+{{ 'Event edit'|trans }}
+
+ {{ form_start(edit_form) }}
+ {{ form_errors(edit_form) }}
+ {{ form_row(edit_form.circle) }}
+ {% if edit_form.center is defined %}
+ {{ form_row(edit_form.center) }}
+ {% endif %}
+ {{ form_row(edit_form.name) }}
+ {{ form_row(edit_form.date) }}
+ {{ form_row(edit_form.type, { 'label': 'Event type' }) }}
+
+
+
+ {{ form_end(edit_form) }}
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Event/index.html.twig b/src/Bundle/ChillEvent/Resources/views/Event/index.html.twig
new file mode 100644
index 000000000..442d5ca67
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Event/index.html.twig
@@ -0,0 +1,43 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Event list
+
+
+
+
+ Id |
+ Name |
+ Date |
+ Actions |
+
+
+
+ {% for entity in entities %}
+
+ {{ entity.id }} |
+ {{ entity.name }} |
+ {% if entity.date %}{{ entity.date|date('Y-m-d H:i:s') }}{% endif %} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Event/list.html.twig b/src/Bundle/ChillEvent/Resources/views/Event/list.html.twig
new file mode 100644
index 000000000..6c78a49e1
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Event/list.html.twig
@@ -0,0 +1,66 @@
+{{ 'Event search'|trans }}
+
+{% transchoice total with { '%pattern%' : pattern } %}%total% events match the search %pattern%{% endtranschoice %}
+
+{% if events|length > 0 %}
+
+ {{ 'Results %start%-%end% of %total%'|trans({ '%start%' : start, '%end%': start + events|length, '%total%' : total } ) }}
+
+
+
+
+ {{ 'Name'|trans }} |
+ {{ 'Date'|trans }} |
+ {{ 'Event type'|trans }} |
+ |
+
+
+
+ {% for event in events %}
+
+ {{ event.name }} |
+ {{ event.date|localizeddate('long', 'none') }} |
+ {{ event.type.name|localize_translatable_string }} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+{% endif %}
+
+
+
+{% if preview == false %}
+{{ chill_pagination(paginator) }}
+{% endif %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Event/new.html.twig b/src/Bundle/ChillEvent/Resources/views/Event/new.html.twig
new file mode 100644
index 000000000..1c29a495d
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Event/new.html.twig
@@ -0,0 +1,29 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% block title 'Event creation'|trans %}
+
+{% block event_content -%}
+ {{ 'Event creation'|trans }}
+
+ {{ form_start(form) }}
+ {{ form_errors(form) }}
+ {{ form_row(form.circle) }}
+ {{ form_row(form.center) }}
+ {{ form_row(form.name) }}
+ {{ form_row(form.date) }}
+ {{ form_row(form.type, { 'label': 'Event type' }) }}
+
+
+
+ {{ form_end(form) }}
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Event/show.html.twig b/src/Bundle/ChillEvent/Resources/views/Event/show.html.twig
new file mode 100644
index 000000000..e2aa9caf3
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Event/show.html.twig
@@ -0,0 +1,99 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% block title 'Event : %label%'|trans({ '%label%' : event.name } ) %}
+
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% block event_content -%}
+ {{ 'Details of an event'|trans }}
+
+
+
+
+ {{ 'Name'|trans }} |
+ {{ event.name }} |
+
+
+ {{ 'Date'|trans }} |
+ {{ event.date|localizeddate('long', 'none') }} |
+
+
+ {{ 'Event type'|trans }} |
+ {{ event.type.name|localize_translatable_string }} |
+
+
+ {{ 'Circle'|trans }} |
+ {{ event.circle.name|localize_translatable_string }} |
+
+
+
+
+
+
+ {{ 'Participations'|trans }}
+ {% set count = event.participations|length %}
+ {% transchoice count %}%count% participations to this event{% endtranschoice %}
+
+ {% if count > 0 %}
+
+
+
+ {{ 'Person'|trans }} |
+ {{ 'Role'|trans }} |
+ {{ 'Status'|trans }} |
+ {{ 'Last update'|trans }} |
+ |
+
+
+
+ {% for participation in event.participations %}
+
+ {{ person_macro.render(participation.person) }} |
+ {{ participation.role.name|localize_translatable_string }} |
+ {{ participation.status.name|localize_translatable_string }} |
+ {{ participation.lastUpdate|time_diff }} |
+
+
+ {% if is_granted('CHILL_EVENT_PARTICIPATION_UPDATE', participation) %}
+ -
+
+ {{ 'Edit'|trans }}
+
+
+ {% endif %}
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endif %}
+
+
+
+
+ {{ form_start(form_add_participation_by_person) }}
+ {{ form_widget(form_add_participation_by_person.person_id, { 'attr' : { 'style' : 'width: 25em; display:inline-block; ' } } ) }}
+ {{ form_widget(form_add_participation_by_person.submit, { 'attr' : { 'class' : 'sc-button bt-create' } } ) }}
+ {{ form_rest(form_add_participation_by_person) }}
+ {{ form_end(form_add_participation_by_person) }}
+
+
+
+ {{ chill_delegated_block('block_footer_show', { 'event': event }) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/EventType/edit.html.twig b/src/Bundle/ChillEvent/Resources/views/EventType/edit.html.twig
new file mode 100644
index 000000000..92bf5a236
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/EventType/edit.html.twig
@@ -0,0 +1,16 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ EventType edit
+
+ {{ form(edit_form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/EventType/index.html.twig b/src/Bundle/ChillEvent/Resources/views/EventType/index.html.twig
new file mode 100644
index 000000000..669384172
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/EventType/index.html.twig
@@ -0,0 +1,43 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ EventType list
+
+
+
+
+ Id |
+ Label |
+ Active |
+ Actions |
+
+
+
+ {% for entity in entities %}
+
+ {{ entity.id }} |
+ {{ entity.name|localize_translatable_string }} |
+ {{ entity.active }} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/EventType/new.html.twig b/src/Bundle/ChillEvent/Resources/views/EventType/new.html.twig
new file mode 100644
index 000000000..69a8f2638
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/EventType/new.html.twig
@@ -0,0 +1,15 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ EventType creation
+
+ {{ form(form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/EventType/show.html.twig b/src/Bundle/ChillEvent/Resources/views/EventType/show.html.twig
new file mode 100644
index 000000000..df2712898
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/EventType/show.html.twig
@@ -0,0 +1,36 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ EventType
+
+
+
+
+ Id |
+ {{ entity.id }} |
+
+
+ Name |
+ {{ entity.name|localize_translatable_string }} |
+
+
+ Active |
+ {{ entity.active }} |
+
+
+
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Participation/_ignored_participations.html.twig b/src/Bundle/ChillEvent/Resources/views/Participation/_ignored_participations.html.twig
new file mode 100644
index 000000000..0d54dd624
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Participation/_ignored_participations.html.twig
@@ -0,0 +1,10 @@
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% if ignored_participations|length > 0 %}
+ {% transchoice ignored_participations|length %}The following people have been ignored because they are already participating on the event{% endtranschoice %} :
+
+ {% for p in ignored_participations %}
+ - {{ person_macro.render(p.person) }}
+ {% endfor %}
+
+{% endif %}
\ No newline at end of file
diff --git a/src/Bundle/ChillEvent/Resources/views/Participation/edit-multiple.html.twig b/src/Bundle/ChillEvent/Resources/views/Participation/edit-multiple.html.twig
new file mode 100644
index 000000000..747b53260
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Participation/edit-multiple.html.twig
@@ -0,0 +1,60 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% block event_content -%}
+ {{ 'Participation Edit'|trans }}
+
+
+
+
+ {{ 'Associated event'|trans }} |
+ {{ event.name }} |
+
+
+ {{ 'Date'|trans }} |
+ {{ event.date|localizeddate('long', 'none') }} |
+
+
+
+
+ {{ 'Participations'|trans }}
+
+ {{ form_start(form) }}
+
+
+
+
+ {{ 'Person'|trans }} |
+ {{ 'Role'|trans }} |
+ {{ 'Status'|trans }} |
+ {{ 'Last update'|trans }} |
+ |
+
+
+
+ {% for participation in form.participations %}
+
+ {{ person_macro.render(participation.vars.value.person) }} |
+ {{ form_widget(participation.role) }} |
+ {{ form_widget(participation.status) }} |
+ {{ participation.vars.value.lastUpdate|time_diff }} |
+
+ {% endfor %}
+
+
+
+
+
+ {{ form_end(form) }}
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Participation/edit.html.twig b/src/Bundle/ChillEvent/Resources/views/Participation/edit.html.twig
new file mode 100644
index 000000000..a778eeef7
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Participation/edit.html.twig
@@ -0,0 +1,42 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% block event_content -%}
+ {{ 'Participation Edit'|trans }}
+
+
+
+
+ {{ 'Associated person'|trans }} |
+ {{ person_macro.render(participation.person) }} |
+
+
+ {{ 'Associated event'|trans }} |
+ {{ participation.event.name }} |
+
+
+ {{ 'Date'|trans }} |
+ {{ participation.event.date|localizeddate('long', 'none') }} |
+
+
+
+
+ {{ form_start(form) }}
+ {{ form_row(form.role) }}
+ {{ form_row(form.status) }}
+
+
+
+ {{ form_end(form) }}
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Participation/new-multiple.html.twig b/src/Bundle/ChillEvent/Resources/views/Participation/new-multiple.html.twig
new file mode 100644
index 000000000..8cdfed800
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Participation/new-multiple.html.twig
@@ -0,0 +1,68 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% block title 'Participation creation'|trans %}
+
+ {% form_theme form _self %}
+
+ {% block _collection_row %}
+
+
+ {{ form_widget(form) }}
+ |
+
+ {# {{ form_row(participationField.status) }} #}
+ |
+
+ {% endblock %}
+
+{% block event_content -%}
+ {{ 'Participation creation'|trans }}
+
+
+
+
+ {{ 'Associated event'|trans }} |
+ {{ participations[0].event.name }} |
+
+
+
+
+ {% include 'ChillEventBundle:Participation:_ignored_participations.html.twig' with ignored_participations %}
+
+ {{ form_start(form) }}
+
+
+
+ {{ 'Person'|trans }} |
+ {{ 'Role'|trans }} |
+ {{ 'Status'|trans }} |
+
+
+
+ {% for participationField in form.participations %}
+
+ {{ person_macro.render(participationField.vars.value.person) }} |
+ {{ form_widget(participationField.role) }} |
+ {{ form_widget(participationField.status) }} |
+
+ {% endfor %}
+
+
+
+
+
+ {{ form_end(form) }}
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Participation/new.html.twig b/src/Bundle/ChillEvent/Resources/views/Participation/new.html.twig
new file mode 100644
index 000000000..7ec10fa5f
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Participation/new.html.twig
@@ -0,0 +1,48 @@
+{% extends 'ChillEventBundle::layout.html.twig' %}
+
+{% import 'ChillPersonBundle:Person:macro.html.twig' as person_macro %}
+
+{% block title 'Participation creation'|trans %}
+
+{% block event_content -%}
+ {{ 'Participation creation'|trans }}
+
+
+
+
+ {{ 'Associated person'|trans }} |
+ {{ person_macro.render(participation.person) }} |
+
+
+ {{ 'Associated event'|trans }} |
+ {{ participation.event.name }} |
+
+
+
+
+ {% include 'ChillEventBundle:Participation:_ignored_participations.html.twig' with ignored_participations %}
+
+ {{ form_start(form) }}
+
+ {{ form_errors(form) }}
+
+ {{ form_row(form.role) }}
+ {{ form_row(form.status) }}
+
+
+
+
+
+ {{ form_end(form) }}
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Role/edit.html.twig b/src/Bundle/ChillEvent/Resources/views/Role/edit.html.twig
new file mode 100644
index 000000000..021c810d6
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Role/edit.html.twig
@@ -0,0 +1,16 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Role edit
+
+ {{ form(edit_form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Role/index.html.twig b/src/Bundle/ChillEvent/Resources/views/Role/index.html.twig
new file mode 100644
index 000000000..5ac43d05e
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Role/index.html.twig
@@ -0,0 +1,43 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Role list
+
+
+
+
+ Id |
+ Name |
+ Active |
+ Actions |
+
+
+
+ {% for entity in entities %}
+
+ {{ entity.id }} |
+ {{ entity.name|localize_translatable_string }} |
+ {{ entity.active }} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Role/new.html.twig b/src/Bundle/ChillEvent/Resources/views/Role/new.html.twig
new file mode 100644
index 000000000..fd3c82044
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Role/new.html.twig
@@ -0,0 +1,15 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Role creation
+
+ {{ form(form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Role/show.html.twig b/src/Bundle/ChillEvent/Resources/views/Role/show.html.twig
new file mode 100644
index 000000000..5a6956e76
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Role/show.html.twig
@@ -0,0 +1,36 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Role
+
+
+
+
+ Id |
+ {{ entity.id }} |
+
+
+ Name |
+ {{ entity.name|localize_translatable_string }} |
+
+
+ Active |
+ {{ entity.active }} |
+
+
+
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Status/edit.html.twig b/src/Bundle/ChillEvent/Resources/views/Status/edit.html.twig
new file mode 100644
index 000000000..8c610c130
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Status/edit.html.twig
@@ -0,0 +1,16 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Status edit
+
+ {{ form(edit_form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Status/index.html.twig b/src/Bundle/ChillEvent/Resources/views/Status/index.html.twig
new file mode 100644
index 000000000..38f34f955
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Status/index.html.twig
@@ -0,0 +1,43 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Status list
+
+
+
+
+ Id |
+ Name |
+ Active |
+ Actions |
+
+
+
+ {% for entity in entities %}
+
+ {{ entity.id }} |
+ {{ entity.name|localize_translatable_string }} |
+ {{ entity.active }} |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Status/new.html.twig b/src/Bundle/ChillEvent/Resources/views/Status/new.html.twig
new file mode 100644
index 000000000..bd2d824fa
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Status/new.html.twig
@@ -0,0 +1,15 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Status creation
+
+ {{ form(form) }}
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/Status/show.html.twig b/src/Bundle/ChillEvent/Resources/views/Status/show.html.twig
new file mode 100644
index 000000000..8aa32d1a2
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/Status/show.html.twig
@@ -0,0 +1,36 @@
+{% extends '::base.html.twig' %}
+
+{% block body -%}
+ Status
+
+
+
+
+ Id |
+ {{ entity.id }} |
+
+
+ Name |
+ {{ entity.name|localize_translatable_string }} |
+
+
+ Active |
+ {{ entity.active }} |
+
+
+
+
+
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Resources/views/layout.html.twig b/src/Bundle/ChillEvent/Resources/views/layout.html.twig
new file mode 100644
index 000000000..3b1a4d092
--- /dev/null
+++ b/src/Bundle/ChillEvent/Resources/views/layout.html.twig
@@ -0,0 +1,25 @@
+{#
+ * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
+ /
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+#}
+
+{% extends "ChillMainBundle::layoutWithVerticalMenu.html.twig" %}
+
+{% block layout_wvm_content %}
+ {% block event_content %}
+ {{ 'Event' |trans }}
+ {% endblock %}
+{% endblock %}
diff --git a/src/Bundle/ChillEvent/Search/EventSearch.php b/src/Bundle/ChillEvent/Search/EventSearch.php
new file mode 100644
index 000000000..ae900b4c3
--- /dev/null
+++ b/src/Bundle/ChillEvent/Search/EventSearch.php
@@ -0,0 +1,214 @@
+
+ * @author Champs Libres
+ */
+class EventSearch extends AbstractSearch
+{
+
+ /**
+ *
+ * @var EntityRepository
+ */
+ private $er;
+
+ /**
+ *
+ * @var \Chill\MainBundle\Entity\User
+ */
+ private $user;
+
+ /**
+ *
+ * @var AuthorizationHelper
+ */
+ private $helper;
+
+ /**
+ *
+ * @var TemplatingEngine
+ */
+ private $templating;
+
+ /**
+ *
+ * @var PaginatorFactory
+ */
+ private $paginationFactory;
+
+ const NAME = 'event_regular';
+
+ public function __construct(
+ TokenStorageInterface $tokenStorage,
+ EntityRepository $eventRepository,
+ AuthorizationHelper $authorizationHelper,
+ TemplatingEngine $templating,
+ PaginatorFactory $paginatorFactory
+ )
+ {
+ $this->user = $tokenStorage->getToken()->getUser();
+ $this->er = $eventRepository;
+ $this->helper = $authorizationHelper;
+ $this->templating = $templating;
+ $this->paginationFactory = $paginatorFactory;
+ }
+
+ public function supports($domain)
+ {
+ return 'event' === $domain or 'events' === $domain;
+ }
+
+ public function isActiveByDefault()
+ {
+ return true;
+ }
+
+ public function getOrder()
+ {
+ return 3000;
+ }
+
+ public function renderResult(array $terms, $start = 0, $limit = 50,
+ array $options = array())
+ {
+ $total = $this->count($terms);
+ $paginator = $this->paginationFactory->create($total);
+
+ return $this->templating->render('ChillEventBundle:Event:list.html.twig',
+ array(
+ 'events' => $this->search($terms, $start, $limit, $options),
+ 'pattern' => $this->recomposePattern($terms, $this->getAvailableTerms(), $terms['_domain']),
+ 'total' => $total,
+ 'start' => $start,
+ 'preview' => $options[SearchInterface::SEARCH_PREVIEW_OPTION],
+ 'paginator' => $paginator,
+ 'search_name' => self::NAME
+ ));
+ }
+
+ protected function getAvailableTerms()
+ {
+ return array('date-from', 'date-to', 'name', 'date');
+ }
+
+ protected function search(array $terms, $start, $limit, $options)
+ {
+ $qb = $this->er->createQueryBuilder('e');
+ $qb->select('e');
+ $this->composeQuery($qb, $terms)
+ ->setMaxResults($limit)
+ ->setFirstResult($start)
+ ->orderBy('e.date', 'DESC')
+ ;
+
+ return $qb->getQuery()->getResult();
+ }
+
+ protected function count(array $terms)
+ {
+ $qb = $this->er->createQueryBuilder('e');
+ $qb->select('COUNT(e)');
+ $this->composeQuery($qb, $terms)
+ ;
+
+ return $qb->getQuery()->getSingleScalarResult();
+ }
+
+ protected function composeQuery(QueryBuilder &$qb, $terms)
+ {
+
+ // add security clauses
+ $reachableCenters = $this->helper
+ ->getReachableCenters($this->user, new Role('CHILL_EVENT_SEE'));
+
+ if (count($reachableCenters) === 0) {
+ // add a clause to block all events
+ $where = $qb->expr()->isNull('e.center');
+ $qb->andWhere($where);
+ } else {
+
+ $n = 0;
+ $orWhere = $qb->expr()->orX();
+ foreach ($reachableCenters as $center) {
+ $circles = $this->helper->getReachableScopes($this->user,
+ new Role('CHILL_EVENT_SEE'), $center);
+ $where = $qb->expr()->andX(
+ $qb->expr()->eq('e.center', ':center_'.$n),
+ $qb->expr()->in('e.circle', ':circle_'.$n)
+ );
+ $qb->setParameter('center_'.$n, $center);
+ $qb->setParameter('circle_'.$n, $circles);
+ $orWhere->add($where);
+ }
+
+ $qb->andWhere($orWhere);
+ }
+
+ if (
+ (isset($terms['name']) OR isset($terms['_default']))
+ AND
+ (!empty($terms['name']) OR !empty($terms['_default']))) {
+ // the form with name:"xyz" has precedence
+ $name = isset($terms['name']) ? $terms['name'] : $terms['_default'];
+
+ $where = $qb->expr()->like('UNACCENT(LOWER(e.name))', ':name');
+ $qb->setParameter('name', '%'.$name.'%');
+ $qb->andWhere($where);
+ }
+
+ if (isset($terms['date'])) {
+ $date = $this->parseDate($terms['date']);
+
+ $where = $qb->expr()->eq('e.date', ':date');
+ $qb->setParameter('date', $date);
+ $qb->andWhere($where);
+ }
+
+ if (isset($terms['date-from'])) {
+ $date = $this->parseDate($terms['date-from']);
+
+ $where = $qb->expr()->gte('e.date', ':datefrom');
+ $qb->setParameter('datefrom', $date);
+ $qb->andWhere($where);
+ }
+
+ if (isset($terms['date-to'])) {
+ $date = $this->parseDate($terms['date-to']);
+
+ $where = $qb->expr()->lte('e.date', ':dateto');
+ $qb->setParameter('dateto', $date);
+ $qb->andWhere($where);
+ }
+
+
+
+ return $qb;
+ }
+}
diff --git a/src/Bundle/ChillEvent/Security/Authorization/EventVoter.php b/src/Bundle/ChillEvent/Security/Authorization/EventVoter.php
new file mode 100644
index 000000000..8f74e649a
--- /dev/null
+++ b/src/Bundle/ChillEvent/Security/Authorization/EventVoter.php
@@ -0,0 +1,70 @@
+
+ * @author Champs Libres
+ */
+class EventVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
+{
+
+ const SEE = 'CHILL_EVENT_SEE';
+ const SEE_DETAILS = 'CHILL_EVENT_SEE_DETAILS';
+ const CREATE = 'CHILL_EVENT_CREATE';
+ const UPDATE = 'CHILL_EVENT_UPDATE';
+
+ protected $authorizationHelper;
+
+ public function __construct(AuthorizationHelper $helper)
+ {
+ $this->authorizationHelper = $helper;
+ }
+
+ protected function getSupportedAttributes()
+ {
+ return array(self::SEE, self::SEE_DETAILS,
+ self::CREATE, self::UPDATE);
+ }
+
+ protected function getSupportedClasses()
+ {
+ return array(Event::class);
+ }
+
+ protected function isGranted($attribute, $event, $user = null)
+ {
+ if (!$user instanceof User) {
+ return false;
+ }
+
+ return $this->authorizationHelper->userHasAccess($user, $event, $attribute);
+ }
+
+ public function getRoles()
+ {
+ return $this->getSupportedAttributes();
+ }
+
+ public function getRolesWithoutScope()
+ {
+ return null;
+ }
+
+
+ public function getRolesWithHierarchy()
+ {
+ return [ 'Event' => $this->getRoles() ];
+ }
+
+}
diff --git a/src/Bundle/ChillEvent/Security/Authorization/ParticipationVoter.php b/src/Bundle/ChillEvent/Security/Authorization/ParticipationVoter.php
new file mode 100644
index 000000000..385796a71
--- /dev/null
+++ b/src/Bundle/ChillEvent/Security/Authorization/ParticipationVoter.php
@@ -0,0 +1,87 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Chill\EventBundle\Security\Authorization;
+
+use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
+use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
+use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
+use Chill\EventBundle\Entity\Participation;
+use Chill\MainBundle\Entity\User;
+
+/**
+ *
+ *
+ * @author Julien Fastré
+ */
+class ParticipationVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
+{
+ /**
+ *
+ * @var AuthorizationHelper
+ */
+ protected $authorizationHelper;
+
+ const CREATE = 'CHILL_EVENT_PARTICIPATION_CREATE';
+ const UPDATE = 'CHILL_EVENT_PARTICIPATION_UPDATE';
+
+ public function __construct(AuthorizationHelper $helper)
+ {
+ $this->authorizationHelper = $helper;
+ }
+
+ protected function getSupportedAttributes()
+ {
+ return array(
+ self::CREATE, self::UPDATE
+ );
+ }
+
+ protected function getSupportedClasses()
+ {
+ return array(
+ Participation::class
+ );
+ }
+
+ protected function isGranted($attribute, $participation, $user = null)
+ {
+ if (!$user instanceof User) {
+ return false;
+ }
+
+ return $this->authorizationHelper->userHasAccess($user, $participation, $attribute);
+ }
+
+ public function getRoles()
+ {
+ return $this->getSupportedAttributes();
+ }
+
+ public function getRolesWithoutScope()
+ {
+ return null;
+ }
+
+ public function getRolesWithHierarchy()
+ {
+ return [ 'Event' => $this->getRoles() ];
+ }
+
+}
diff --git a/src/Bundle/ChillEvent/Tests/Controller/EventControllerTest.php b/src/Bundle/ChillEvent/Tests/Controller/EventControllerTest.php
new file mode 100644
index 000000000..d955d4a56
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Controller/EventControllerTest.php
@@ -0,0 +1,60 @@
+markTestSkipped();
+ }
+ /*
+ public function testCompleteScenario()
+ {
+ // Create a new client to browse the application
+ $client = static::createClient();
+
+ // Create a new entry in the database
+ $crawler = $client->request('GET', '/event/');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /event/");
+ $crawler = $client->click($crawler->selectLink('Create a new entry')->link());
+
+ // Fill in the form and submit it
+ $form = $crawler->selectButton('Create')->form(array(
+ 'chill_eventbundle_event[field_name]' => 'Test',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check data in the show view
+ $this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
+
+ // Edit the entity
+ $crawler = $client->click($crawler->selectLink('Edit')->link());
+
+ $form = $crawler->selectButton('Update')->form(array(
+ 'chill_eventbundle_event[field_name]' => 'Foo',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check the element contains an attribute with value equals "Foo"
+ $this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
+
+ // Delete the entity
+ $client->submit($crawler->selectButton('Delete')->form());
+ $crawler = $client->followRedirect();
+
+ // Check the entity has been delete on the list
+ $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
+ }
+
+ */
+}
diff --git a/src/Bundle/ChillEvent/Tests/Controller/EventTypeControllerTest.php b/src/Bundle/ChillEvent/Tests/Controller/EventTypeControllerTest.php
new file mode 100644
index 000000000..57af95de5
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Controller/EventTypeControllerTest.php
@@ -0,0 +1,59 @@
+markTestSkipped();
+ }
+ /*
+ public function testCompleteScenario()
+ {
+ // Create a new client to browse the application
+ $client = static::createClient();
+
+ // Create a new entry in the database
+ $crawler = $client->request('GET', '/{_locale}/admin/');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /{_locale}/admin/");
+ $crawler = $client->click($crawler->selectLink('Create a new entry')->link());
+
+ // Fill in the form and submit it
+ $form = $crawler->selectButton('Create')->form(array(
+ 'chill_eventbundle_eventtype[field_name]' => 'Test',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check data in the show view
+ $this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
+
+ // Edit the entity
+ $crawler = $client->click($crawler->selectLink('Edit')->link());
+
+ $form = $crawler->selectButton('Update')->form(array(
+ 'chill_eventbundle_eventtype[field_name]' => 'Foo',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check the element contains an attribute with value equals "Foo"
+ $this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
+
+ // Delete the entity
+ $client->submit($crawler->selectButton('Delete')->form());
+ $crawler = $client->followRedirect();
+
+ // Check the entity has been delete on the list
+ $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
+ }
+
+ */
+}
diff --git a/src/Bundle/ChillEvent/Tests/Controller/ParticipationControllerTest.php b/src/Bundle/ChillEvent/Tests/Controller/ParticipationControllerTest.php
new file mode 100644
index 000000000..a51fae197
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Controller/ParticipationControllerTest.php
@@ -0,0 +1,448 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Chill\EventBundle\Tests\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+
+/**
+ * Test the creation of participation controller
+ *
+ *
+ * @author Julien Fastré
+ */
+class ParticipationControllerTest extends WebTestCase
+{
+ /**
+ *
+ * @var \Symfony\Component\BrowserKit\Client
+ */
+ protected $client;
+
+ /**
+ *
+ * @var \Doctrine\ORM\EntityManagerInterface
+ */
+ protected $em;
+
+ /**
+ * Keep a cache for each person id given by the function getRandomPerson.
+ *
+ * You may ask to ignore some people by adding their id to the array.
+ *
+ * This is reset by setUp().
+ *
+ * @var int[]
+ */
+ private $personsIdsCache = array();
+
+ public function setUp()
+ {
+ self::bootKernel();
+
+ $this->client = static::createClient(array(), array(
+ 'PHP_AUTH_USER' => 'center a_social',
+ 'PHP_AUTH_PW' => 'password',
+ 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR'
+ ));
+
+ $container = self::$kernel->getContainer();
+
+ $this->em = $container->get('doctrine.orm.entity_manager')
+ ;
+
+ $this->personsIdsCache = array();
+ }
+
+ /**
+ *
+ *
+ * @return \Chill\EventBundle\Entity\Event
+ */
+ protected function getRandomEvent($centerName = 'Center A', $circleName = 'social')
+ {
+ $center = $this->em->getRepository('ChillMainBundle:Center')
+ ->findByName($centerName);
+
+ $circles = $this->em->getRepository('ChillMainBundle:Scope')
+ ->findAll();
+ array_filter($circles, function($circle) use ($circleName) {
+ return in_array($circleName, $circle->getName());
+ });
+ $circle = $circles[0];
+
+ $events = $this->em->getRepository('ChillEventBundle:Event')
+ ->findBy(array('center' => $center, 'circle' => $circle));
+
+ return $events[array_rand($events)];
+ }
+
+ /**
+ * Return a random event only if he has more than one participation.
+ *
+ * @param string $centerName
+ * @param type $circleName
+ * @return \Chill\EventBundle\Entity\Event
+ */
+ protected function getRandomEventWithMultipleParticipations(
+ $centerName = 'Center A',
+ $circleName = 'social')
+ {
+ $event = $this->getRandomEvent($centerName, $circleName);
+
+ return $event->getParticipations()->count() > 1 ?
+ $event :
+ $this->getRandomEventWithMultipleParticipations($centerName, $circleName);
+ }
+
+ /**
+ * Returns a person randomly.
+ *
+ * This function does not give the same person twice
+ * for each test.
+ *
+ * You may ask to ignore some people by adding their id to the property
+ * `$this->personsIdsCache`
+ *
+ * @param string $centerName
+ * @return \Chill\PersonBundle\Entity\Person
+ */
+ protected function getRandomPerson($centerName = 'Center A')
+ {
+ $center = $this->em->getRepository('ChillMainBundle:Center')
+ ->findByName($centerName);
+
+ $persons = $this->em->getRepository('ChillPersonBundle:Person')
+ ->findBy(array('center' => $center));
+
+ $person = $persons[array_rand($persons)];
+
+ if (in_array($person->getId(), $this->personsIdsCache)) {
+ return $this->getRandomPerson($centerName); // we try another time
+ } else {
+ $this->personsIdsCache[] = $person->getId();
+ return $person;
+ }
+
+ }
+
+ public function testNewActionWrongParameters()
+ {
+ $event = $this->getRandomEvent();
+ $person = $this->getRandomPerson();
+
+ // missing person_id or persons_ids
+ $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'event_id' => $event->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/new fail if "
+ . "both person_id and persons_ids are missing");
+
+ // having both person_id and persons_ids
+ $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'event_id' => $event->getId(),
+ 'persons_ids' => implode(',', array(
+ $this->getRandomPerson()->getId(),
+ $this->getRandomPerson()->getId()
+ )),
+ 'person_id' => $person->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/new fail if both person_id and "
+ . "persons_ids are set");
+
+ // missing event_id
+ $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'person_id' => $person->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/new fails if event_id is missing");
+
+ // persons_ids with wrong content
+ $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'persons_ids' => 'a,b,531',
+ 'event_id' => $event->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/new fails if persons_ids has wrong content");
+ }
+
+ /**
+ * This method test participation creation with wrong parameters.
+ *
+ * Those request should fail before any processing.
+ */
+ public function testCreateActionWrongParameters()
+ {
+ $event = $this->getRandomEvent();
+ $person = $this->getRandomPerson();
+
+ // missing person_id or persons_ids
+ $this->client->request('GET', '/fr/event/participation/create',
+ array(
+ 'event_id' => $event->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/create fail if "
+ . "both person_id and persons_ids are missing");
+
+ // having both person_id and persons_ids
+ $this->client->request('GET', '/fr/event/participation/create',
+ array(
+ 'event_id' => $event->getId(),
+ 'persons_ids' => implode(',', array(
+ $this->getRandomPerson()->getId(),
+ $this->getRandomPerson()->getId()
+ )),
+ 'person_id' => $person->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/create fail if both person_id and "
+ . "persons_ids are set");
+
+ // missing event_id
+ $this->client->request('GET', '/fr/event/participation/create',
+ array(
+ 'person_id' => $person->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/create fails if event_id is missing");
+
+ // persons_ids with wrong content
+ $this->client->request('GET', '/fr/event/participation/create',
+ array(
+ 'persons_ids' => 'a,b,531',
+ 'event_id' => $event->getId()
+ ));
+ $this->assertEquals(400, $this->client->getResponse()->getStatusCode(),
+ "Test that /fr/event/participation/create fails if persons_ids has wrong content");
+ }
+
+ public function testNewSingleAction()
+ {
+ $event = $this->getRandomEvent();
+ // record the number of participation for the event
+ $nbParticipations = $event->getParticipations()->count();
+ $person = $this->getRandomPerson();
+
+ $crawler = $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'person_id' => $person->getId(),
+ 'event_id' => $event->getId()
+ ));
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/new is successful");
+
+ $button = $crawler->selectButton('Créer');
+
+ $this->assertNotNull($button, "test the form with button 'Créer' exists");
+
+ $this->client->submit($button->form(), array(
+ 'participation[role]' => $event->getType()->getRoles()->first()->getId(),
+ 'participation[status]' => $event->getType()->getStatuses()->first()->getId()
+ ));
+
+ $this->assertTrue($this->client->getResponse()->isRedirect());
+ $crawler = $this->client->followRedirect();
+
+ $span = $crawler->filter('table td span.entity-person a:contains("'
+ .$person->getFirstName().'"):contains("'.$person->getLastname().'")');
+
+ $this->assertGreaterThan(0, count($span));
+
+ // as the container has reloaded, reload the event
+ $event = $this->em->getRepository('ChillEventBundle:Event')->find($event->getId());
+ $this->em->refresh($event);
+
+ $this->assertEquals($nbParticipations + 1, $event->getParticipations()->count());
+ }
+
+ public function testNewMultipleAction()
+ {
+ $event = $this->getRandomEvent();
+ // record the number of participation for the event (used later in this test)
+ $nbParticipations = $event->getParticipations()->count();
+ // make ignore the people already in the event from the function getRandomPerson
+ $this->personsIdsCache = array_merge(
+ $this->personsIdsCache,
+ $event->getParticipations()->map(
+ function($p) { return $p->getPerson()->getId(); }
+ )
+ ->toArray()
+ );
+ // get some random people
+ $person1 = $this->getRandomPerson();
+ $person2 = $this->getRandomPerson();
+
+ $crawler = $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'persons_ids' => implode(',', array($person1->getId(), $person2->getId())),
+ 'event_id' => $event->getId()
+ ));
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/new is successful");
+
+ $button = $crawler->selectButton('Créer');
+
+ $this->assertNotNull($button, "test the form with button 'Créer' exists");
+
+ $this->client->submit($button->form(), array(
+ 'form' => array(
+ 'participations' => array(
+ 0 => array(
+ 'role' => $event->getType()->getRoles()->first()->getId(),
+ 'status' => $event->getType()->getStatuses()->first()->getId()
+ ),
+ 1 => array(
+ 'role' => $event->getType()->getRoles()->first()->getId(),
+ 'status' => $event->getType()->getStatuses()->first()->getId()
+ ),
+ )
+ )
+ ));
+
+ $this->assertTrue($this->client->getResponse()->isRedirect());
+ $crawler = $this->client->followRedirect();
+
+ $span1 = $crawler->filter('table td span.entity-person a:contains("'
+ .$person1->getFirstName().'"):contains("'.$person1->getLastname().'")');
+ $this->assertGreaterThan(0, count($span1));
+ $span2 = $crawler->filter('table td span.entity-person a:contains("'
+ .$person2->getFirstName().'"):contains("'.$person2->getLastname().'")');
+ $this->assertGreaterThan(0, count($span2));
+
+ // as the container has reloaded, reload the event
+ $event = $this->em->getRepository('ChillEventBundle:Event')->find($event->getId());
+ $this->em->refresh($event);
+
+ $this->assertEquals($nbParticipations + 2, $event->getParticipations()->count());
+ }
+
+ public function testNewMultipleWithAllPeopleParticipating()
+ {
+ $event = $this->getRandomEventWithMultipleParticipations();
+
+ $persons_id = implode(',', $event->getParticipations()->map(
+ function($p) { return $p->getPerson()->getId(); }
+ )->toArray());
+
+ $crawler = $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'persons_ids' => $persons_id,
+ 'event_id' => $event->getId()
+ ));
+
+ $this->assertEquals(302, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/new is redirecting");
+ }
+
+ public function testNewMultipleWithSomePeopleParticipating()
+ {
+ $event = $this->getRandomEventWithMultipleParticipations();
+ // record the number of participation for the event (used later in this test)
+ $nbParticipations = $event->getParticipations()->count();
+ // get the persons_id participating on this event
+ $persons_id = $event->getParticipations()->map(
+ function($p) { return $p->getPerson()->getId(); }
+ )->toArray();
+ // exclude the existing persons_ids from the new person
+ $this->personsIdsCache = array_merge($this->personsIdsCache, $persons_id);
+
+ // get a random person
+ $newPerson = $this->getRandomPerson();
+
+ // build the `persons_ids` parameter
+ $persons_ids_string = implode(',', array_merge($persons_id,
+ array($newPerson->getId())));
+
+ $crawler = $this->client->request('GET', '/fr/event/participation/new',
+ array(
+ 'persons_ids' => $persons_ids_string,
+ 'event_id' => $event->getId()
+ ));
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode(),
+ "test that /fr/event/participation/new is successful");
+
+ // count that the one UL contains the new person string
+ $firstPerson = $event->getParticipations()->first()->getPerson();
+ $ul = $crawler->filter('ul:contains("'.$firstPerson->getLastName().'")'
+ . ':contains("'.$firstPerson->getFirstName().'")');
+
+ $this->assertEquals(1, $ul->count(),
+ "assert an ul containing the name of ignored people is present");
+ $this->assertEquals($event->getParticipations()->count(), $ul->children()->count(),
+ "assert the li listing ignored people has the correct number");
+
+ // test a form is present on the page
+ $button = $crawler->selectButton('Créer');
+
+ $this->assertNotNull($button, "test the form with button 'Créer' exists");
+
+ // submit the form
+ $this->client->submit($button->form(), array(
+ 'participation[role]' => $event->getType()->getRoles()->first()->getId(),
+ 'participation[status]' => $event->getType()->getStatuses()->first()->getId()
+ ));
+
+ $this->assertTrue($this->client->getResponse()->isRedirect());
+
+ // reload the event and test there is a new participation
+ $event = $this->em->getRepository('ChillEventBundle:Event')
+ ->find($event->getId());
+ $this->em->refresh($event);
+
+ $this->assertEquals($nbParticipations + 1, $event->getParticipations()->count(),
+ "Test we have persisted a new participation associated to the test");
+ }
+
+ public function testEditMultipleAction()
+ {
+ /* @var $event \Chill\EventBundle\Entity\Event */
+ $event = $this->getRandomEventWithMultipleParticipations();
+
+ $crawler = $this->client->request('GET', '/fr/event/participation/'.$event->getId().
+ '/edit_multiple');
+
+ $this->assertEquals(200, $this->client->getResponse()->getStatusCode());
+
+ $button = $crawler->selectButton('Mettre à jour');
+ $this->assertEquals(1, $button->count(), "test the form with button 'mettre à jour' exists ");
+
+
+ $this->client->submit($button->form(), array(
+ 'form[participations][0][role]' => $event->getType()->getRoles()->first()->getId(),
+ 'form[participations][0][status]' => $event->getType()->getStatuses()->first()->getId(),
+ 'form[participations][1][role]' => $event->getType()->getRoles()->last()->getId(),
+ 'form[participations][1][status]' => $event->getType()->getStatuses()->last()->getId(),
+ ));
+
+ $this->assertTrue($this->client->getResponse()
+ ->isRedirect('/fr/event/event/'.$event->getId().'/show'));
+ }
+
+
+}
diff --git a/src/Bundle/ChillEvent/Tests/Controller/RoleControllerTest.php b/src/Bundle/ChillEvent/Tests/Controller/RoleControllerTest.php
new file mode 100644
index 000000000..f2286f208
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Controller/RoleControllerTest.php
@@ -0,0 +1,59 @@
+markTestSkipped();
+ }
+ /*
+ public function testCompleteScenario()
+ {
+ // Create a new client to browse the application
+ $client = static::createClient();
+
+ // Create a new entry in the database
+ $crawler = $client->request('GET', '/{_locale}/admin/role/');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /{_locale}/admin/role/");
+ $crawler = $client->click($crawler->selectLink('Create a new entry')->link());
+
+ // Fill in the form and submit it
+ $form = $crawler->selectButton('Create')->form(array(
+ 'chill_eventbundle_role[field_name]' => 'Test',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check data in the show view
+ $this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
+
+ // Edit the entity
+ $crawler = $client->click($crawler->selectLink('Edit')->link());
+
+ $form = $crawler->selectButton('Update')->form(array(
+ 'chill_eventbundle_role[field_name]' => 'Foo',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check the element contains an attribute with value equals "Foo"
+ $this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
+
+ // Delete the entity
+ $client->submit($crawler->selectButton('Delete')->form());
+ $crawler = $client->followRedirect();
+
+ // Check the entity has been delete on the list
+ $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
+ }
+
+ */
+}
diff --git a/src/Bundle/ChillEvent/Tests/Controller/StatusControllerTest.php b/src/Bundle/ChillEvent/Tests/Controller/StatusControllerTest.php
new file mode 100644
index 000000000..99e297575
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Controller/StatusControllerTest.php
@@ -0,0 +1,59 @@
+markTestSkipped();
+ }
+ /*
+ public function testCompleteScenario()
+ {
+ // Create a new client to browse the application
+ $client = static::createClient();
+
+ // Create a new entry in the database
+ $crawler = $client->request('GET', '/fr/admin/event/status/');
+ $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /fr/admin/event/status/");
+ $crawler = $client->click($crawler->selectLink('Create a new entry')->link());
+
+ // Fill in the form and submit it
+ $form = $crawler->selectButton('Create')->form(array(
+ 'chill_eventbundle_status[field_name]' => 'Test',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check data in the show view
+ $this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
+
+ // Edit the entity
+ $crawler = $client->click($crawler->selectLink('Edit')->link());
+
+ $form = $crawler->selectButton('Update')->form(array(
+ 'chill_eventbundle_status[field_name]' => 'Foo',
+ // ... other fields to fill
+ ));
+
+ $client->submit($form);
+ $crawler = $client->followRedirect();
+
+ // Check the element contains an attribute with value equals "Foo"
+ $this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
+
+ // Delete the entity
+ $client->submit($crawler->selectButton('Delete')->form());
+ $crawler = $client->followRedirect();
+
+ // Check the entity has been delete on the list
+ $this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
+ }
+
+ */
+}
diff --git a/src/Bundle/ChillEvent/Tests/Search/EventSearchTest.php b/src/Bundle/ChillEvent/Tests/Search/EventSearchTest.php
new file mode 100644
index 000000000..bb31a7bfa
--- /dev/null
+++ b/src/Bundle/ChillEvent/Tests/Search/EventSearchTest.php
@@ -0,0 +1,398 @@
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+namespace Chill\EventBundle\Tests\Search;
+
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+use Chill\EventBundle\Entity\Event;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Chill\EventBundle\Search\EventSearch;
+
+
+/**
+ * Test the EventSearch class
+ *
+ * @author Julien Fastré
+ */
+class EventSearchTest extends WebTestCase
+{
+ /**
+ * The eventSearch service, which is used to search events
+ *
+ * @var \Chill\EventBundle\Search\EventSearch
+ */
+ protected $eventSearch;
+
+ /**
+ *
+ * @var \Doctrine\ORM\EntityManagerInterface
+ */
+ protected $entityManager;
+
+ /**
+ * The center A
+ *
+ * @var \Chill\MainBundle\Entity\Center
+ */
+ protected $centerA;
+
+ /**
+ * a random event type
+ *
+ * @var \Chill\EventBundle\Entity\EventType
+ */
+ protected $eventType;
+
+ /**
+ * Events created during this test
+ *
+ * @var Event[]
+ */
+ protected $events = array();
+
+ /**
+ *
+ * @var \Prophecy\Prophet
+ */
+ protected $prophet;
+
+ /**
+ *
+ * @var \Symfony\Component\BrowserKit\Client
+ */
+ protected $client;
+
+ public function setUp()
+ {
+ self::bootKernel();
+ /* @var $kernel \Symfony\Component\HttpKernel\KernelInterface */
+ $kernel = self::$kernel;
+
+ $this->client = static::createClient(array(), array(
+ 'PHP_AUTH_USER' => 'center a_social',
+ 'PHP_AUTH_PW' => 'password',
+ 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR'
+ ));
+
+ $this->prophet = new \Prophecy\Prophet;
+
+ $this->entityManager = self::$kernel->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ;
+
+ $this->centerA = $this->entityManager
+ ->getRepository('ChillMainBundle:Center')
+ ->findOneBy(array('name' => 'Center A'));
+
+ $this->eventType = $this->entityManager
+ ->getRepository('ChillEventBundle:EventType')
+ ->findAll()[0];
+
+ $this->createEvents();
+ }
+
+ public function tearDown()
+ {
+ foreach ($this->events as $event) {
+ $this->entityManager->createQuery('DELETE FROM ChillEventBundle:Event e WHERE e.id = :event_id')
+ ->setParameter('event_id', $event->getId())
+ ->execute();
+ }
+
+ $this->events = array();
+ }
+
+ protected function createEvents()
+ {
+ $event1 = (new Event())
+ ->setCenter($this->centerA)
+ ->setDate(new \DateTime('2016-05-30'))
+ ->setName('Printemps européen')
+ ->setType($this->eventType)
+ ->setCircle($this->getCircle())
+ ;
+ $this->entityManager->persist($event1);
+ $this->events[] = $event1;
+
+ $event2 = (new Event())
+ ->setCenter($this->centerA)
+ ->setDate(new \DateTime('2016-06-24'))
+ ->setName('Hiver de la droite')
+ ->setType($this->eventType)
+ ->setCircle($this->getCircle())
+ ;
+ $this->entityManager->persist($event2);
+ $this->events[] = $event2;
+
+ $this->entityManager->flush();
+ }
+
+ /**
+ *
+ * @param string $name the name of the circle
+ * @return \Chill\MainBundle\Entity\Scope
+ */
+ protected function getCircle($name = 'social')
+ {
+ $circles = $this->entityManager->getRepository('ChillMainBundle:Scope')
+ ->findAll();
+
+ /* @var $circle \Chill\MainBundle\Entity\Scope */
+ foreach($circles as $circle) {
+ if (in_array($name, $circle->getName())) {
+ return $circle;
+ }
+ }
+ }
+
+ public function testDisplayAll()
+ {
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events'
+ ));
+
+ $this->assertGreaterThanOrEqual(2, $crawler->filter('table.events tr')->count(),
+ 'assert than more than 2 tr are present');
+ }
+
+ public function testSearchByDefault()
+ {
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events printemps'
+ ));
+
+ $this->assertEquals(
+ 1,
+ $crawler->filter('table.events tr')->count() - 1 /* as the header is a th */,
+ 'assert than more than 2 tr are present');
+
+ $this->assertEquals(
+ 1,
+ $crawler->filter('tr:contains("Printemps")')->count(),
+ 'assert that the word "printemps" is present');
+ }
+
+ public function testSearchByName()
+ {
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events name:printemps'
+ ));
+
+ $this->assertEquals(
+ 1,
+ $crawler->filter('table.events tr')->count() - 1 /* as the header is a th */,
+ 'assert than more than 2 tr are present');
+
+ $this->assertEquals(
+ 1,
+ $crawler->filter('tr:contains("Printemps")')->count(),
+ 'assert that the word "printemps" is present');
+ }
+
+ public function testSearchByDateDateFromOnly()
+ {
+ // search with date from
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events date-from:2016-05-30'
+ ));
+ /* @var $dateFrom \DateTime the date from in DateTime */
+ $dateFrom = \DateTime::createFromFormat("Y-m-d", "2016-05-30");
+
+ $dates = $this->iterateOnRowsToFindDate($crawler->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ }
+
+ // click on link "Voir tous les résultats"
+ $crawlerAllResults = $this->client->click($crawler
+ ->selectLink("Voir tous les résultats")->link());
+ $dates = $this->iterateOnRowsToFindDate($crawlerAllResults->filter("tr"));
+
+ foreach ($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ }
+
+ //iterate on pagination
+ $crawlerAllResults->filter(".pagination a")->each(function($a, $i) use ($dateFrom) {
+ $page = $this->client->click($a->link());
+ $dates = $this->iterateOnRowsToFindDate($page->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ }
+ });
+ }
+
+ public function testSearchByDateDateBetween()
+ {
+ // serach with date from **and** date-to
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events date-from:2016-05-30 date-to:2016-06-20'
+ ));
+
+ /* @var $dateFrom \DateTime the date from in DateTime */
+ $dateFrom = \DateTime::createFromFormat("Y-m-d", "2016-05-30");
+ $dateTo = \DateTime::createFromFormat("Y-m-d", "2016-06-20");
+
+ $dates = $this->iterateOnRowsToFindDate($crawler->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+
+ // there should not have any other results, but if any other bundle
+ // add some other event, we go on next pages
+
+ if ($crawler->selectLink("Voir tous les résultats")->count() == 0) {
+ return ;
+ }
+
+ // click on link "Voir tous les résultats"
+ $crawlerAllResults = $this->client->click($crawler
+ ->selectLink("Voir tous les résultats")->link());
+ $dates = $this->iterateOnRowsToFindDate($crawlerAllResults->filter("tr"));
+
+ foreach ($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+
+ //iterate on pagination
+ $crawlerAllResults->filter(".pagination a")->each(function($a, $i) use ($dateFrom) {
+ $page = $this->client->click($a->link());
+ $dates = $this->iterateOnRowsToFindDate($page->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertGreaterThanOrEqual($dateFrom, $date);
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+ });
+ }
+
+ public function testSearchByDateDateTo()
+ {
+
+ // serach with date from **and** date-to
+ $crawler = $this->client->request('GET', '/fr/search', array(
+ 'q' => '@events date:2016-05-30'
+ ));
+
+ /* @var $dateFrom \DateTime the date from in DateTime */
+ $dateTo = \DateTime::createFromFormat("Y-m-d", "2016-05-30");
+
+ $dates = $this->iterateOnRowsToFindDate($crawler->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+
+ if ($crawler->selectLink("Voir tous les résultats")->count() == 0) {
+ return ;
+ }
+
+ // click on link "Voir tous les résultats"
+ $crawlerAllResults = $this->client->click($crawler
+ ->selectLink("Voir tous les résultats")->link());
+ $dates = $this->iterateOnRowsToFindDate($crawlerAllResults->filter("tr"));
+
+ foreach ($dates as $date) {
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+
+ //iterate on pagination
+ $crawlerAllResults->filter(".pagination a")->each(function($a, $i) use ($dateFrom) {
+ $page = $this->client->click($a->link());
+ $dates = $this->iterateOnRowsToFindDate($page->filter("tr"));
+
+ foreach($dates as $date) {
+ $this->assertLessThanOrEqual($dateTo, $date);
+ }
+ });
+
+ }
+
+ /**
+ * this function iterate on row from results of events and return the content
+ * of the second column (which should contains the date) in DateTime objects
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $trs
+ * @return \DateTime[]
+ */
+ private function iterateOnRowsToFindDate(\Symfony\Component\DomCrawler\Crawler $trs)
+ {
+ $months = array(
+ "janvier" => 1,
+ "février" => 2,
+ "mars" => 3,
+ "avril" => 4,
+ "mai" => 5,
+ "juin" => 6,
+ "juillet" => 7,
+ "août" => 8,
+ "septembre" => 9,
+ "octobre" => 10,
+ "novembre" => 11,
+ "décembre" => 12
+ );
+
+
+ $results = $trs->each(function($tr, $i) use ($months) {
+ // we skip the first row
+ if ($i > 0) {
+ // get the second node, which should contains a date
+ $tdDate = $tr->filter("td")->eq(1);
+ // transform the date, which should be in french, into a DateTime object
+ $parts = explode(" ", $tdDate->text());
+ return \DateTime::createFromFormat("Y-m-d", $parts[2].
+ "-".$months[$parts[1]]."-".$parts[0]);
+ }
+ });
+
+ // remove the first row
+ unset($results[0]);
+
+ return $results;
+ }
+
+ /**
+ * Test that a user connected with an user with the wrong center does not
+ * see the events
+ */
+ public function testDisplayAllWrongUser()
+ {
+ $client = static::createClient(array(), array(
+ 'PHP_AUTH_USER' => 'center b_social',
+ 'PHP_AUTH_PW' => 'password',
+ 'HTTP_ACCEPT_LANGUAGE' => 'fr_FR'
+ ));
+
+ $crawler = $client->request('GET', '/fr/search', array(
+ 'q' => '@events printemps'
+ ));
+
+ $this->assertEquals(0, $crawler->filter('tr:contains("Printemps")')->count(),
+ 'assert that the word "printemps" is present');
+
+ }
+
+
+
+}
diff --git a/src/Bundle/ChillEvent/apigen.neon b/src/Bundle/ChillEvent/apigen.neon
new file mode 100644
index 000000000..7b4c4afc0
--- /dev/null
+++ b/src/Bundle/ChillEvent/apigen.neon
@@ -0,0 +1,12 @@
+# configuration for apigen
+
+
+source:
+ - .
+
+exclude:
+ - vendor/*
+ - Resources/test/*
+
+title: Chill EventBundle
+
diff --git a/src/Bundle/ChillEvent/composer.json b/src/Bundle/ChillEvent/composer.json
new file mode 100644
index 000000000..0a887a2d0
--- /dev/null
+++ b/src/Bundle/ChillEvent/composer.json
@@ -0,0 +1,63 @@
+{
+ "name": "chill-project/event",
+ "description": "This bundle extend chill software. This bundle allow to define event and participation to those events.",
+ "type": "symfony-bundle",
+ "license": "AGPL-3.0",
+ "keywords" : ["chill", "social work"],
+ "homepage" : "https://git.framasoft.org/Chill-project/Chill-Group",
+ "autoload": {
+ "psr-4": { "Chill\\EventBundle\\": "" }
+ },
+ "support": {
+ "issues": "https://git.framasoft.org/Chill-project/Chill-Event/issues",
+ "source": "https://git.framasoft.org/Chill-project/Chill-Event",
+ "docs" : "http://docs.chill.social",
+ "email": "dev@listes.chill.social"
+ },
+ "authors": [
+ {
+ "name": "Champs-Libres",
+ "email": "info@champs-libres.coop"
+ }
+ ],
+ "require": {
+ "twig/extensions": "^1.2",
+ "symfony/assetic-bundle": "~2.3",
+ "symfony/framework-bundle": "~2.7",
+ "symfony/yaml": "~2.8",
+ "symfony/symfony": "~2.8",
+ "doctrine/dbal": "~2.5",
+ "doctrine/orm": "~2.4",
+ "doctrine/common": "~2.4",
+ "doctrine/doctrine-bundle": "~1.2",
+ "chill-project/main": "dev-master@dev",
+ "chill-project/person": "dev-master@dev",
+ "champs-libres/composer-bundle-migration": "~1.0",
+ "doctrine/doctrine-migrations-bundle": "~1.1",
+ "chill-project/custom-fields": "dev-master@dev",
+ "doctrine/migrations": "~1.0",
+ "monolog/monolog": "^1.14"
+ },
+ "require-dev": {
+ "doctrine/doctrine-fixtures-bundle": "~2.2",
+ "fzaninotto/faker": "~1",
+ "symfony/monolog-bundle": "^2.7",
+ "sensio/generator-bundle": "^2.5"
+ },
+ "suggest" : {
+ "chill-project/group": "dev-master@dev"
+ },
+ "scripts": {
+ "post-install-cmd": [
+ "ComposerBundleMigration\\Composer\\Migrations::synchronizeMigrations"
+ ],
+ "post-update-cmd": [
+ "ComposerBundleMigration\\Composer\\Migrations::synchronizeMigrations"
+ ]
+ },
+ "extra": {
+ "app-migrations-dir": "Resources/test/Fixtures/App/DoctrineMigrations"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/src/Bundle/ChillEvent/phpunit.xml.dist b/src/Bundle/ChillEvent/phpunit.xml.dist
new file mode 100644
index 000000000..cb1f867cf
--- /dev/null
+++ b/src/Bundle/ChillEvent/phpunit.xml.dist
@@ -0,0 +1,23 @@
+
+
+
+
+
+ ./Tests
+
+
+
+
+ ./
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
+
+
+
+
+