Compare commits

...

146 Commits

Author SHA1 Message Date
Huaoe b5791997d8 Merge remote-tracking branch 'origin/master' into feat/push
# Conflicts:
#	volume/www/website/www/app/config/fos_elastica.yml
#	volume/www/website/www/src/AppBundle/Entity/User.php
#	volume/www/website/www/web/assetic/main.dash.talent.js
#	volume/www/website/www/web/css/styles.css
2019-09-02 10:30:32 +02:00
Huaoe d51add8f1d comment yellow bar 2019-09-02 09:31:47 +02:00
Huaoe 579c800dc9 📲 2019-08-29 16:01:46 +02:00
Huaoe 24897eab5e space 2019-08-29 15:59:52 +02:00
Sébastien GLATZ bde2c84cde Add banner for new app 2019-08-29 15:56:04 +02:00
Huaoe eee791b08f address in add company 2019-08-27 16:52:35 +02:00
Huaoe 874027d494 chat messages api done 2019-08-26 15:16:46 +02:00
Thomas Berrod 328a3821b8 message 2019-08-21 17:30:54 +02:00
Thomas Berrod 807a9351ea facebook stalling 2019-08-19 17:19:33 +02:00
Thomas Berrod 21f5912384 wkf Answer + reset password 2019-08-12 15:45:29 +02:00
Thomas Berrod 2d35cd41f1 formating 2019-08-09 15:14:52 +02:00
Thomas Berrod 04a3a0d9c7 bug fix :undefined varible 2019-08-09 15:14:13 +02:00
Thomas Berrod be7e738839 test join company 2019-08-09 14:53:32 +02:00
Thomas Berrod 67825d024d Company join on ads 2019-08-09 11:50:47 +02:00
Thomas Berrod 85ba5dcbae thomas email change 2019-08-09 09:47:42 +02:00
Thomas Berrod b914b0ea96 answer directly to status SENDED 2019-08-08 15:43:14 +02:00
Thomas Berrod 48240d5cab fix : candidature spontanée even if answered to ad 2019-08-08 15:38:05 +02:00
Thomas Berrod c1dc54d036 comment out 2019-08-07 17:09:44 +02:00
Thomas Berrod c801856bfc filtre company 2019-08-07 17:05:01 +02:00
Thomas Berrod e8c9052e35 exposing businessname on ad_detail 2019-08-06 11:18:04 +02:00
Thomas Berrod b86aa8960b bug fix on POST answer 2019-08-05 17:00:37 +02:00
Thomas Berrod c770fd16c2 $token missing 2019-08-01 17:18:31 +02:00
gregoire 36fa91f2b3 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-08-01 14:53:11 +02:00
gregoire ff55b409e0 variable verification + security 2019-08-01 14:53:05 +02:00
Thomas Berrod ee57f4ebaf fix echo in login facebook flow 2019-07-31 15:02:07 +02:00
Thomas Berrod cd3b2986a5 fix facebook email issue 2019-07-31 14:56:50 +02:00
Thomas Berrod 79a075a034 facebook use accesstoken for profile fetch 2019-07-31 14:37:22 +02:00
Thomas Berrod ad8581d9e7 facebook get profil PROD access code 2019-07-31 11:11:38 +02:00
Thomas Berrod 371493e01f Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-30 17:12:58 +02:00
Thomas Berrod 64210c330b hard change facebook access_token 2019-07-30 17:12:54 +02:00
Thomas Berrod 088f7f2edc creation time added to JSON answers... 2019-07-30 17:12:12 +02:00
Thomas Berrod d01afc28aa bug fix offre pourvues 2019-07-30 15:27:39 +02:00
gregoire d831ffaff5 Only one answer by user / offer implementation 2019-07-30 10:15:34 +02:00
gregoire f540542aa0 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-26 10:22:00 +02:00
Thomas Berrod dd9d6f7901 Answers fixes 2019-07-25 14:56:06 +02:00
gregoire 714bd5ff87 debut Exception 2019-07-25 09:15:55 +02:00
gregoire 9cb079cbba question readme + spontaneous answer 2019-07-23 17:29:01 +02:00
gregoire 8003feec05 Post answer 2019-07-23 16:34:17 +02:00
gregoire 4616dbd65a add type annotation 2019-07-23 12:08:29 +02:00
Thomas Berrod 1ef4a57848 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-22 17:36:40 +02:00
Thomas Berrod 8bae304f0d beginnings on post answers 2019-07-22 17:36:27 +02:00
gregoire acacaae6de readme notification + public key 2019-07-22 17:29:44 +02:00
Thomas Berrod fb8239e987 groups on company / ads 2019-07-22 11:38:42 +02:00
gregoire 088e680230 change keys for push notification 2019-07-22 10:01:43 +02:00
Thomas Berrod 2fdc095c31 "company_detail" added 2019-07-19 16:53:55 +02:00
Thomas Berrod 4ca1962829 zzz off 2019-07-19 16:49:35 +02:00
Thomas Berrod 19e3b11066 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 16:49:04 +02:00
Thomas Berrod ef2550568f Revert "Add group serializer"
This reverts commit b50ad1de77.
2019-07-19 16:48:40 +02:00
gregoire 9845e11954 fuck 2019-07-19 16:48:40 +02:00
gregoire 0447b333ec fix problem website + test 2019-07-19 16:48:40 +02:00
Thomas Berrod fb58eaec0f company search fix 2019-07-19 16:48:40 +02:00
gregoire b145eb1628 fix company for user 2019-07-19 16:48:40 +02:00
Sébastien GLATZ d29cb07d46 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 16:33:23 +02:00
Sébastien GLATZ b50ad1de77 Add group serializer 2019-07-19 16:33:12 +02:00
gregoire 4cad444833 fuck 2019-07-19 16:13:20 +02:00
gregoire 94885d96bc fix problem website + test 2019-07-19 14:54:39 +02:00
gregoire 6902b005b4 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 14:17:47 +02:00
gregoire 2b9abe5bec fix company for user 2019-07-19 14:16:46 +02:00
Thomas Berrod 8fa429e35a Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 14:09:32 +02:00
Sébastien GLATZ 81eb21d84b Add group serializer 2019-07-19 11:45:01 +02:00
Thomas Berrod 097dd88b5e company search fix 2019-07-19 09:21:13 +02:00
gregoire 527ab850db regex for requirements companycontroller 2019-07-18 11:04:27 +02:00
gregoire fbc2e414ea securit.yml correction + add extra serialize group 2019-07-18 09:57:07 +02:00
gregoire c81b5e9c51 Add comment in serialize answer + path security 2019-07-18 09:30:32 +02:00
gregoire 57e5c2eff6 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 17:12:58 +02:00
gregoire 6e29500a1b ORM pdf schema + serialize candidature 2019-07-17 17:12:53 +02:00
Sébastien GLATZ 23423cd831 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 14:41:43 +02:00
Sébastien GLATZ 3e2827d624 Add group serializer 2019-07-17 14:41:35 +02:00
Thomas Berrod 08bb1ea10e bug fix : search company on brandName 2019-07-17 12:09:14 +02:00
Thomas Berrod f1e23410d4 bug fix : to lower search 2019-07-17 11:13:52 +02:00
Thomas Berrod 922f526ddd bug fix : consecutive where setparrameter distinct id 2019-07-17 11:12:28 +02:00
Thomas Berrod 9a4de2f6ca company emphasis 2019-07-17 10:13:10 +02:00
gregoire a4995ac616 Reset Password API 2019-07-17 10:08:49 +02:00
Sébastien GLATZ 8f70911b2e Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 08:37:08 +02:00
Sébastien GLATZ 54c255cf33 Add group serializer to is_promoted (pourvue) 2019-07-17 08:37:00 +02:00
gregoire 553727cbe1 Add UpdateUser function for API 2019-07-16 15:49:35 +02:00
gregoire 783485b96e merge emphasis 2019-07-16 11:33:15 +02:00
gregoire f01215b074 countAds implementation 2019-07-16 11:25:29 +02:00
Thomas Berrod e65afe3b24 emphasis 2019-07-16 11:18:50 +02:00
Thomas Berrod c3696934e9 push params prod config 2019-07-16 09:20:06 +02:00
Thomas Berrod 12cc628f14 preprod conf 2019-07-11 11:07:21 +02:00
Thomas Berrod c63302acbf Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-11 10:27:18 +02:00
Sébastien GLATZ 6aa736a4a2 Update serialized field 2019-07-11 10:23:56 +02:00
Sébastien GLATZ 05ceeb440e Add countAds 2019-07-11 10:23:56 +02:00
Sébastien GLATZ 539878e73b Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-09 09:26:29 +02:00
Thomas Berrod 1c7a1732a6 slug service fix 2019-07-08 18:37:50 +02:00
Thomas Berrod ac975c7604 fix findUserWithFacebookEmailAndAttach 2019-07-08 18:26:27 +02:00
Thomas Berrod 56d2f199b5 remove dumps 2019-07-08 18:22:17 +02:00
Thomas Berrod 1a3955a605 composer update 2019-07-08 14:50:37 +02:00
Sébastien GLATZ e69b5d80cd Update API data 2019-07-08 10:02:14 +02:00
Thomas Berrod 8706d63867 api register + twig loginbutton logical fix 2019-07-05 15:26:11 +02:00
Thomas Berrod 8c0c1f7720 return $data->elements[0]->{'handle~'}->emailAdress; 2019-07-04 17:41:12 +02:00
Thomas Berrod 2628883568 typo 2019-07-04 17:33:29 +02:00
Thomas Berrod 8918b3708b linkedin double request for email 2019-07-04 17:19:58 +02:00
Thomas Berrod f75989129e docker file + facebook photo 2019-07-03 17:11:27 +02:00
Thomas Berrod 0b563e9658 security config + fetch user 2019-06-21 16:28:03 +02:00
Thomas Berrod 9e70ee745b removed proxy generation during dev 2019-06-20 17:24:58 +02:00
Thomas Berrod 3bdc496c03 company groups stable 2019-06-20 12:12:46 +02:00
Thomas Berrod 1cccee38b8 Rest auth facebook linkedin Beta 2019-06-17 17:36:09 +02:00
Thomas Berrod a97a794dec media upload config 2019-06-05 11:59:24 +02:00
Sébastien GLATZ 1c2a944ca5 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push
# Conflicts:
#	conf/build/php/Dockerfile
2019-05-29 14:31:13 +02:00
Sébastien GLATZ 08555463fd Ajout groupes de sérialization 2019-05-29 14:24:03 +02:00
Thomas Berrod a8c04f48b0 #9658 first upload Answer controller 2019-05-23 15:04:47 +02:00
Thomas Berrod 0c86cd00ac #9658 : first media upload 2019-05-23 15:04:17 +02:00
Sébastien GLATZ 60365023ac Feat : Ajout groupe sérialisation pour API 2019-05-22 10:06:24 +02:00
Sébastien GLATZ 2c40323718 Fix : Modification configurations base + libpng-dev 2019-05-22 09:57:30 +02:00
Thomas Berrod 76a028cd88 Fix: typo + company search 2019-05-17 15:38:59 +02:00
Thomas Berrod 52ad0cf32e Fix : typo 2019-05-16 15:19:51 +02:00
Thomas Berrod 7e94b1e104 delete makefile backup 2019-05-16 10:18:14 +02:00
Thomas Berrod 54e971d918 make file windows compat 2019-05-16 10:17:43 +02:00
Thomas Berrod 3a82158fe3 deletes 2019-05-16 10:14:05 +02:00
Thomas Berrod 34b3e260bc Merge branch 'feat/api-rest' into feat/push
# Conflicts:
#	Makefile
2019-05-16 10:13:28 +02:00
Thomas Berrod 362006818e makefile 2019-05-16 09:58:18 +02:00
Thomas Berrod d6f8941e47 unknown deletes 2019-05-16 09:46:59 +02:00
Thomas Berrod 0d0c725aaf dernier travaux sur notif : voir les todos 2019-02-05 12:07:41 +01:00
Thomas Berrod a5742f2c1e typo sur offstet 2018-09-24 16:33:55 +02:00
Thomas Berrod 57b7db7f43 styling notification toast 2018-09-20 11:51:17 +02:00
Thomas Berrod db07bc80c8 analytics plug on push 2018-09-19 13:57:12 +02:00
Thomas Berrod 1e03451b37 notification param in talent/me + delayed trigger on 3 times entreprise viewed 2018-09-18 16:48:56 +02:00
Maxime Thévenot b1185018de Feat : composer update after merge 2018-09-17 12:30:04 +02:00
Maxime Thévenot 5d8357231c Conf : add gmp to php container 2018-09-17 12:29:42 +02:00
Thomas Berrod 5474397f5f Merge branch 'feat/api-rest' of https://git.e-declic.net/talents-tube/website into feat/api-rest 2018-09-17 10:49:18 +02:00
Maxime Thévenot aeb4328e23 Merge branch 'feat/api-rest' into feat/push
# Conflicts:
#	volume/www/website/www/app/AppKernel.php
#	volume/www/website/www/app/config/config.yml
#	volume/www/website/www/app/config/parameters-dev.yml
#	volume/www/website/www/app/config/parameters.yml.dist
#	volume/www/website/www/app/config/routing.yml
#	volume/www/website/www/app/config/services.yml
#	volume/www/website/www/composer.json
#	volume/www/website/www/composer.lock
#	volume/www/website/www/vendor/composer/autoload_files.php
#	volume/www/website/www/vendor/composer/autoload_psr4.php
#	volume/www/website/www/vendor/composer/autoload_static.php
#	volume/www/website/www/vendor/composer/installed.json
#	volume/www/website/www/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
#	volume/www/website/www/web/css/styles.css
2018-09-17 10:29:41 +02:00
Maxime Thévenot 44d0711dc1 Feat : Add company and answer api base 2018-09-17 10:15:12 +02:00
Thomas Berrod 9f6c1a740f Merge branch 'feat/api-rest' of https://git.e-declic.net/talents-tube/website into feat/api-rest 2018-09-17 09:04:25 +02:00
Thomas Berrod 8063c8479e feat:adding quotes to makefile 2018-09-10 09:53:07 +02:00
Thomas Berrod 56444f6363 feat: update coriolis json 2018-09-10 09:04:00 +02:00
Maxime Thévenot 04229b0781 Feat : implement token generation with facebook id 2018-09-07 14:31:32 +02:00
Maxime Thévenot 4edfae9f1c Feat : implement JWT for api authentication 2018-09-07 08:57:44 +02:00
Maxime Thévenot 870654c850 Feat : update ads representation 2018-09-06 09:48:12 +02:00
Maxime Thévenot 9413202660 WIP : test authentication for api 2018-09-06 08:20:27 +02:00
Maxime Thévenot 215e325a8c Feat : configure and test api on add 2018-09-06 08:20:09 +02:00
Maxime Thévenot 9f8682c896 Feat : Install hateoas bundle 2018-09-06 08:19:16 +02:00
Thomas Berrod ff33129d80 merge windows makefile 2018-09-03 17:28:40 +02:00
Thomas Berrod 1b76548c91 Merge branch 'push_feature' of https://git.e-declic.net/talents-tube/website into push_feature 2018-09-03 17:18:52 +02:00
Thomas Berrod 9578eb96c9 profil & tags ùatching push 2018-09-03 17:14:46 +02:00
Thomas Berrod c4af665c26 general + email + profil completeness 2018-08-31 17:36:01 +02:00
Maxime Thévenot c48fe53e6a Feat : install pagerfante bundle and update api 2018-08-31 16:44:42 +02:00
Maxime Thévenot d69f32c657 Feat : update config.yml for fosrest and add some api method 2018-08-31 12:07:29 +02:00
Maxime Thévenot dba776d15f Update : symfony to 3.4 + vendors 2018-08-31 11:26:11 +02:00
Maxime Thévenot bb3ed610ab WIP : testing api 2018-08-31 10:40:47 +02:00
Maxime Thévenot 75145d9e1c Feat : install FOSRestBundle 2018-08-29 15:26:50 +02:00
Maxime Thévenot b885e6866c Feat : install jmsserializer bundle 2018-08-29 14:42:12 +02:00
Maxime Thévenot dbb06990d5 Conf: update uglify-js to uglify-es 2018-08-29 12:01:23 +02:00
Maxime Thévenot f8c0b75ec2 Conf : update docker config for windows compatbility 2018-08-29 11:56:57 +02:00
Thomas Berrod dca95338a9 push localhost only 2018-08-28 15:12:51 +02:00
13510 changed files with 468763 additions and 152875 deletions
+2
View File
@@ -10,3 +10,5 @@
volume/www/website/.idea
/volume/www/website/store/themes/talentstube-20170413/cache/*
/volume/www/website/store/img/tmp/*
volume/www/website/www/app/Resources/views/default/index.html.twig
TODO
+16 -5
View File
@@ -2,7 +2,7 @@
CLIENT=tt-website
DOCKERCOMPOSE := $(shell command -v docker-compose 2> /dev/null)
USAGE := Usage: make ENV={prod|preprod|dev} {docker-build|docker-start|docker-stop|docker-restart}
USAGE := Usage: make ENV={prod|preprod|dev} {SYS=windows|linux} {docker-build|docker-start|docker-stop|docker-restart}
ifndef DOCKERCOMPOSE
$(error docker-compose is not available)
@@ -14,10 +14,17 @@ $(info $(USAGE))
$(error Exiting)
endif
SYS=linux
DC_OVERRIDE := $(shell test -e conf/docker-compose.override.yml && echo "--file conf/docker-compose.override.yml")
DC_OVERRIDE_ENV := $(shell test -e conf/docker-compose.$(ENV).yml && echo "--file conf/docker-compose.$(ENV).yml")
DC=ENV=$(ENV) CLIENT=$(CLIENT) $(DOCKERCOMPOSE) --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
ifeq ($(SYS),linux)
DC=ENV=$(ENV) CLIENT=$(CLIENT) "$(DOCKERCOMPOSE)" --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
else
DC=ENV=$(ENV) CLIENT=$(CLIENT) "$(DOCKERCOMPOSE)" --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.win.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
endif
default:
$(info $(USAGE))
@@ -77,8 +84,8 @@ db-backup-store:
db-restore-all: db-restore-website db-restore-store
db-restore-website:
@echo "Restoring file to database (backup/store-mysql.sql)"
@cat backup/postgres.sql | docker exec -i $(CLIENT).postgres.$(ENV) psql --dbname database -U postgres
@echo "Restoring file to database (backup/postgres.sql)"
@cat backup/postgres.sql | docker exec -i $(CLIENT).postgres.$(ENV) psql --dbname database -U user
@docker cp backup/mongo $(CLIENT).mongo.$(ENV):/
@docker exec -t $(CLIENT).mongo.$(ENV) mongorestore --drop --gzip --db=tt_history /mongo/tt_history
@@ -95,7 +102,7 @@ entities:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:generate:entities AppBundle"
db-diff:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:migrations:diff"
@docker exec -i $(CLIENT).php.$(ENV) su www-data -c "/home/www/website/www/bin/console doctrine:migrations:diff"
db-migrate:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:migrations:migrate"
@@ -104,3 +111,7 @@ db-deploy: db-diff db-migrate
es-populate:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console fos:elastica:populate"
sys:
@echo $(SYS)
@echo $(DC)
+3
View File
@@ -0,0 +1,3 @@
Todo:
☐ Item
+10 -4
View File
@@ -2,8 +2,7 @@ FROM php:7.1-fpm
ENV TERM=xterm
RUN echo 'deb http://ftp.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/debian-backports.list
RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list.d/debian-backports.list
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
@@ -12,7 +11,14 @@ RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client nodejs npm \
&& apt-get -y install libgmp-dev \
&& ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/local/include/gmp.h \
&& docker-php-ext-install gmp \
&& docker-php-ext-configure gmp
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client nodejs npm \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
@@ -40,7 +46,7 @@ RUN curl --location --silent --show-error https://symfony.com/installer -o /usr/
RUN curl --location --silent --show-error https://s3.amazonaws.com/files.drush.org/drush.phar -o /usr/local/bin/drush \
&& chmod a+x /usr/local/bin/drush
RUN (npm install -g uglify-js) \
RUN (npm install -g uglify-es) \
&& ln -s /usr/bin/nodejs /usr/local/bin/node
RUN apt-get clean \
+2 -2
View File
@@ -10,7 +10,7 @@ RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
@@ -33,4 +33,4 @@ RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
&& rm -rf /var/lib/apt/lists/
+35
View File
@@ -0,0 +1,35 @@
FROM php:7.1-fpm
ENV TERM=xterm
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
&& pecl install geoip-1.1.1 redis imagick \
&& docker-php-ext-enable geoip redis imagick
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY zz-logformat.conf /usr/local/etc/php-fpm.d/
COPY php.ini /usr/local/etc/php/conf.d/
RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
+7
View File
@@ -0,0 +1,7 @@
date.timezone = Europe/Paris
display_errors = Off
memory_limit = 256M
log_errors = On
error_reporting = E_ALL
error_log = /dev/stdout
report_memleaks = On
@@ -0,0 +1,2 @@
[www]
access.format = "%R [%t] \"%m %r%Q%q\" %s %f %{mili}dms %{kilo}MKb %C%%"
+55
View File
@@ -0,0 +1,55 @@
FROM php:7.1-fpm
ENV TERM=xterm
#RUN echo 'deb http://ftp.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/debian-backports.list
RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list.d/debian-backports.list
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update && apt-get install -my wget gnupg
RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - \
&& apt-get install -y nodejs
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client libgmp-dev nodejs \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache gmp \
&& docker-php-ext-configure gmp \
&& pecl install geoip-1.1.1 redis imagick mongodb \
&& docker-php-ext-enable geoip redis imagick mongodb
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY zz-logformat.conf /usr/local/etc/php-fpm.d/
COPY php.ini /usr/local/etc/php/conf.d/
RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN curl --location --silent --show-error https://symfony.com/installer -o /usr/local/bin/symfony \
&& chmod a+x /usr/local/bin/symfony
RUN curl --location --silent --show-error https://s3.amazonaws.com/files.drush.org/drush.phar -o /usr/local/bin/drush \
&& chmod a+x /usr/local/bin/drush
RUN (npm install -g uglify-es) \
&& ln -s /usr/bin/nodejs /usr/local/bin/node
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
+9
View File
@@ -0,0 +1,9 @@
date.timezone = Europe/Paris
display_errors = Off
memory_limit = 768M
log_errors = On
error_reporting = E_ALL
error_log = /dev/stdout
report_memleaks = On
upload_max_filesize = 512M
post_max_size = 512M
+2
View File
@@ -0,0 +1,2 @@
[www]
access.format = "%R [%t] \"%m %r%Q%q\" %s %f %{mili}dms %{kilo}MKb %C%%"
+75
View File
@@ -0,0 +1,75 @@
version: "3"
services:
##
## WEBSITE RESSOURCES
##
nginx:
build: build/nginx
container_name: ${CLIENT}.nginx.${ENV}
hostname: nginx
volumes:
- ../volume/nginx/etc.nginx.sites-enabled:/etc/nginx/sites-enabled
- ../volume/www:/home/www
restart: always
php:
build: build/php_win
container_name: ${CLIENT}.php.${ENV}
hostname: php
volumes:
- ../volume/www:/home/www
restart: always
postgres:
image: postgres:9.6
container_name: ${CLIENT}.postgres.${ENV}
hostname: postgres
env_file: env/postgres.env
volumes:
- tt-postgres:/var/lib/postgresql/data
restart: always
mongo:
image: mongo:3.4
container_name: ${CLIENT}.mongo.${ENV}
hostname: mongo
volumes:
- tt-mongo:/data/db
restart: always
elasticsearch:
build: build/elasticsearch
container_name: ${CLIENT}.elasticsearch.${ENV}
hostname: elasticsearch
volumes:
- search_db_data:/usr/share/elasticsearch/data
restart: always
##
## STORE RESSOURCES
##
store-php:
build: build/php_light_win
container_name: ${CLIENT}.store-php.${ENV}
hostname: store-php
volumes:
- ../volume/www:/home/www
restart: always
store-mysql:
build: build/mysql
container_name: ${CLIENT}.store-mysql.${ENV}
hostname: store-mysql
env_file: env/store-mysql.env
volumes:
- ../volume/store-mysql/var.lib.mysql:/var/lib/mysql
restart: always
# Elastic does not play well with physical volume (folder rights trouble)
volumes:
? search_db_data
tt-postgres:
external: true
tt-mongo:
external: true
-4
View File
@@ -1,4 +0,0 @@
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=database
MYSQL_USER=user
MYSQL_PASSWORD=
-3
View File
@@ -1,3 +0,0 @@
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
+1
View File
@@ -1 +1,2 @@
conf/nginx.conf
/vendor/
+43
View File
@@ -2,3 +2,46 @@ tt
==
A Symfony project created on February 23, 2017, 1:42 pm.
## To have a representation of entity's mappings
In php container, do php bin/console yuml:mappings
To personnalize, see https://github.com/Nono1971/doctrine-yuml-bundle
## If memory issues when installing bundle
Copy this before composer require : COMPOSER_MEMORY_LIMIT=-1
## To update database schema
In php container, root@php:/home/www/website/www# php bin/console doctrine:schema:update --force
It'll update database based on entities
## To push notifications
- Create new .json file in web/push folder.
- This file is composed of two arrays : parameters, where you select specific subscribers to receive notifications,
and notification, where you write the content.
- Values for parameters :
* "pushType" : define the rule to find subscribers, only one value which fits with next ones. Values : "general", "profil", "users", "tags".
* "profilCompletenessPercentage" : define the % of profil completeness. Works with "profil" value of pushType.
* "users" : enters subscriber's mail. Works with "users" value of pushType.
* "keywords" : enters tags to identify subscribers. Works with "tags" value of pushType.
- Values for notification :
* "title" : the title!
* "body" : the content.
* "icon" : the website icon.
* "image" : to add an image.
* "tag" : Used to regroup notifications.
* "data" : array where you can add "link" property. Link will redirect to the given URL.
* "actions" : array where you can add specific action with "action", "title".
* "badge" : to add an image for small device.
- Open SendPushCommand.php, go to configure(), and change the last line of addOption() for files with your filename.
## Stacktrace exception API
All exceptions catched are written in the dev.log file (for ENV=dev I guess) in the AppBundle/var/logs folder.
To have an exception that can be written in this file, create or use an already existing Exception (in AppBundle/Exception) in your Controller.
## Question to ask to Corentin
* Is there a validation from Talents Tube operator to set the answer status to published?
* Is there a comment to be written when post an answer ? (not here in mock-up)
+13
View File
@@ -49,8 +49,20 @@ class AppKernel extends Kernel
new Http\HttplugBundle\HttplugBundle(),
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
//bentools push
new BenTools\WebPushBundle\WebPushBundle(),
//CookieBar
new Fairlane\CookieConsentBundle\FairlaneCookieConsentBundle(),
//Api
new JMS\SerializerBundle\JMSSerializerBundle(),
new FOS\RestBundle\FOSRestBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
new Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle(),
//CORS
new Nelmio\CorsBundle\NelmioCorsBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
@@ -59,6 +71,7 @@ class AppKernel extends Kernel
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
$bundles[] = new Alex\DoctrineExtraBundle\AlexDoctrineExtraBundle();
$bundles[] = new Onurb\Bundle\YumlBundle\OnurbYumlBundle();
}
return $bundles;
@@ -166,6 +166,10 @@
<source>company.account.password.modify.label</source>
<target>Modifier le mot de passe</target>
</trans-unit>
<trans-unit id="company.account.notifications.title">
<source>company.account.notifications.title</source>
<target>Notifications</target>
</trans-unit>
<trans-unit id="profile.edit.submit">
<source>profile.edit.submit</source>
<target>Sauvegarder mon profil</target>
@@ -15,7 +15,7 @@
j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-P4G65WJ');
})(window, document, 'script', 'dataLayer', 'UA-98246968-1');
</script>
<!-- End Google Tag Manager -->
<script type="text/javascript" defer="defer" src="https://extend.vimeocdn.com/ga/64189815.js"></script>
@@ -70,6 +70,7 @@
{#{% include 'default/alert.html.twig' %}#}
{% include 'default/user_switch.html.twig' %}
{% include 'default/header.html.twig' %}
{% include 'default/props_settings.html.twig' %}
{% block content %}
{% endblock %}
{% include 'default/footer.html.twig' %}
@@ -79,6 +80,7 @@
'@global'
output='assetic/main.js' filter='?uglifyjs2' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
{{ include('FairlaneCookieConsentBundle::cookie-info.html.twig') }}
@@ -194,6 +194,10 @@
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript">
$(document).ready(function(){
//asking for push
EdeclicLib = window.EdeclicLib || {};
EdeclicLib.delayedAsk();
//
$('.tooltipped').tooltip();
$.get( "{{ path('ad_ajaxRecStat',{'id': ad.id }) }}", function( data ) {});
if ($('#modal-answer').length > 0) {
@@ -13,15 +13,17 @@
{% else %}
<div class="header-link header-link-signin right-align">
{% if is_granted('ROLE_TALENT') %}
{% set path = path('talent_dashboard') %}
{% set pathDash = path('talent_dashboard') %}
{% elseif is_granted('ROLE_COMPANY') %}
{% set path = path('company_dashboard') %}
{% set pathDash = path('company_dashboard') %}
{% elseif is_granted('ROLE_TERRITORY') %}
{% set path = path('territory_dashboard') %}
{% set pathDash = path('territory_dashboard') %}
{% elseif is_granted('ROLE_ADMIN') %}
{% set path = path('admin_dashboard') %}
{% set pathDash = path('admin_dashboard') %}
{% else %}
{% set pathDash = path('talent_dashboard') %}
{% endif %}
<a class="btn button-round-small" href="{{ path }}">
<a class="btn button-round-small" href="{{ pathDash }}">
<i class="material-icons">perm_identity</i>
<span>Mon compte</span>
</a>
@@ -3,23 +3,49 @@
<div class="row">
<div class="col s12 m12 l10">
<ul id='dropdown_talents' class='dropdown-content'>
<li><a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><a href="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a></li>
<li><a href="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a></li>
<li><a href="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a></li>
<li><a href="{{ path('talent_cv_import') }}" title="Créer mon CV vidéo">Créer mon CV vidéo</a></li>
<li>
<a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a>
</li>
<li>
<a href="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a>
</li>
<li>
<a href="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a>
</li>
<li>
<a href="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a>
</li>
<li>
<a href="{{ path('talent_cv_import') }}" title="Créer mon CV vidéo">Créer mon CV vidéo</a>
</li>
</ul>
<ul id='dropdown_company' class='dropdown-content'>
<li><a href="{{ path('company_list') }}" title="Les entreprises qui recrutent">Les entreprises qui recrutent</a></li>
<li><a href="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a></li>
<li><a href="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a></li>
<li><a href="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a></li>
<li><a href="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a></li>
<li>
<a href="{{ path('company_list') }}" title="Les entreprises qui recrutent">Les entreprises qui recrutent</a>
</li>
<li>
<a href="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a>
</li>
<li>
<a href="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a>
</li>
<li>
<a href="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a>
</li>
<li>
<a href="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a>
</li>
</ul>
<ul id='dropdown_territoire' class='dropdown-content'>
<li><a href="{{ path('territory_list') }}">Liste des territoires</a></li>
<li><a href="{{ path('page_VideoTerritory') }}">La vidéo territoire</a></li>
<li><a href="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a></li>
<li>
<a href="{{ path('territory_list') }}">Liste des territoires</a>
</li>
<li>
<a href="{{ path('page_VideoTerritory') }}">La vidéo territoire</a>
</li>
<li>
<a href="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a>
</li>
</ul>
<nav>
<div class="nav-wrapper">
@@ -28,16 +54,25 @@
<img src="{{ asset('img/Logo-header.png') }}" alt="Talents Tube"/>
</a>
</div>
<a href="#" data-activates="mobile-demo" class="button-collapse"><i class="material-icons">menu</i></a>
<a href="#" data-activates="mobile-demo" class="button-collapse">
<i class="material-icons">menu</i>
</a>
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-button" data-activates="dropdown_talents" href="{{ path('page_cvVideo') }}"
title="Talents">Talents</a></li>
<li><a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><a class="dropdown-button" data-activates="dropdown_company" href="{{ path('company_list') }}"
title="Les entreprises de talents">Entreprises</a></li>
<li><a class="dropdown-button" data-activates="dropdown_territoire" href="{{ path('territory_list') }}"
title="Les territoires">Territoires</a></li>
<li><a href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a></li>
<li>
<a class="dropdown-button" data-activates="dropdown_talents" href="{{ path('page_cvVideo') }}" title="Talents">Talents</a>
</li>
<li>
<a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a>
</li>
<li>
<a class="dropdown-button" data-activates="dropdown_company" href="{{ path('company_list') }}" title="Les entreprises de talents">Entreprises</a>
</li>
<li>
<a class="dropdown-button" data-activates="dropdown_territoire" href="{{ path('territory_list') }}" title="Les territoires">Territoires</a>
</li>
<li>
<a href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a>
</li>
</ul>
</div>
@@ -48,6 +83,13 @@
</div>
</div>
</div>
{#<div id="newApp" class="container-fluid">
<div class="row">
<div class="col s12 m12">
<p>"Nouveau ! Trouvez un job plus facilement avec notre <a href="http://pp.app.talentstube.com">web application</a>.📲"</p>
</div>
</div>
</div>#}
</div>
<div class="nav-wrapper">
<ul class="side-nav collapsible" data-collapsible="accordion" id="mobile-demo">
@@ -58,10 +100,10 @@
<a class="collapsible-header" title="Talents">Talents</a>
<div class="collapsible-body">
<ul>
<li><a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><a href="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a></li>
<li><a href="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a></li>
<li><a href="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a></li>
<li><ahref="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><ahref="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a></li>
<li><ahref="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a></li>
<li><ahref="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a></li>
</ul>
</div>
</li>
@@ -72,11 +114,11 @@
<a class="collapsible-header" title="Les entreprises de talents">Entreprises</a>
<div class="collapsible-body">
<ul>
<li><a href="{{ path('company_list') }}" title="Listes entreprises">Listes entreprises</a></li>
<li><a href="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a></li>
<li><a href="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a></li>
<li><a href="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a></li>
<li><a href="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a></li>
<li><ahref="{{ path('company_list') }}" title="Listes entreprises">Listes entreprises</a></li>
<li><ahref="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a></li>
<li><ahref="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a></li>
<li><ahref="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a></li>
<li><ahref="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a></li>
</ul>
</div>
</li>
@@ -84,9 +126,9 @@
<a class="collapsible-header" title="Les territoires">Territoires</a>
<div class="collapsible-body">
<ul>
<li><a href="{{ path('territory_list') }}">Liste des territoires</a></li>
<li><a href="{{ path('page_VideoTerritory') }}">La vidéo territoire</a></li>
<li><a href="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a></li>
<li><ahref="{{ path('territory_list') }}">Liste des territoires</a></li>
<li><ahref="{{ path('page_VideoTerritory') }}">La vidéo territoire</a></li>
<li><ahref="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a></li>
</ul>
</div>
</li>
@@ -94,4 +136,4 @@
<a class="collapsible-header" href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a>
</li>
</ul>
</div>
</div>
@@ -19,7 +19,7 @@
</div>
<div class="header-video-inner">
<video loop="" preload="metadata" autoplay="" id="vid" muted="muted">
<source src="/img/home_video.mp4" type="video/mp4">
{# <source src="/img/home_video.mp4" type="video/mp4"> #}
</video>
</div>
@@ -0,0 +1,10 @@
<!-- props_settings.html.twig Parameters used in EdeclicPushAndNotificationClient.js -->
<div id="pushParams"
data-service-worker-url="{{ app.request.uriForPath('/Edeclic-service-worker.js') | replace({'/app_dev.php': ''}) }}"
data-analytics-helper-url="{{ app.request.uriForPath('js/analytics-helper.js') | replace({'/app_dev.php': ''}) }}"
data-delete-subscription-url="{{ url('delete-subscription') }}"
data-save-subscription-url="{{ url('save-subscription') }}"
data-push-public-key="{{ push_public_key }}"
>
</div>
@@ -0,0 +1,23 @@
{% extends 'base.html.twig' %} {% block content %}
<div id="page-static" class="contentWrapper">
<h1 class="alttitle center-align">Test PUSH</h1>
<div class="fluid-container bg-dark2">
<div class="container">
<div class="row first-row">
<div class="col s12 m6 video-wrapper">
<div class="video-container">
<img src="/img/img_content/accompagnement_img.png" alt="accompagnement">
</div>
</div>
<div class="col s12 m6">
<h5 class="m-t-0">TEST PUSH</h5>
<p>
</p>
<p>
</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
@@ -1,8 +1,8 @@
{% extends 'talent/base_dashboard_talent.html.twig' %}
{% block dashContent %}
{% include 'default/props_settings.html.twig' %}
{% include 'default/flash_message.html.twig' %}
<div class=" row bg-bordered p-20">
{#<h1 class="alttitle">{{ 'profile.talent.account.title'|trans }}</h1>#}
@@ -11,18 +11,71 @@
<h4>{{ 'company.account.password.modify'|trans }}</h4>
{% if form_errors(formPw) %}
<div class="card-panel">
<span class="red-text text-darken-2">
{{ form_errors(formPw) }}
</span>
<span class="red-text text-darken-2">
{{ form_errors(formPw) }}
</span>
</div>
{% endif %}
{{ form_start(formPw) }}
{{ form_rest(formPw) }}
<br/>
<input class="btn btn-default" type="submit"
value="{{ 'company.account.password.modify.label'|trans }}"/>
<input class="btn btn-default" type="submit" value="{{ 'company.account.password.modify.label'|trans }}"/>
{{ form_end(formPw) }}
</div>
</div>
</div>
<div class=" row bg-bordered p-20">
<div class="row flexcontainer">
<div class="col s12">
<h4>{{ 'company.account.notifications.title'|trans }}</h4>
<br/>
<input type="checkbox" id="notificationChecked" name="notificationChecked" {{isNotificationAllowed ? "checked=checked":""}}/>
<label for="notificationChecked">Autoriser les notificaitons</label>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$('#notificationChecked').on('click', function (event) {
let EdeclicLib = window.EdeclicLib;
let notifConsent = $('#notificationChecked').is(":checked");
if (notifConsent == true) {
//ask for subscription
var promise1 = new Promise(EdeclicLib.askForNotifications)
.then(() => $('#notificationChecked').prop('checked', true), () => $('#notificationChecked').prop('checked', false))
.catch((err) => {
$('#notificationChecked').prop('checked', false);
alert(err);
});
} else {
//require unsubscription
EdeclicLib.unsubscribe();
$.ajax({
async: true,
type: 'POST',
url: '{{ url('talent_notification_consent') }}',
data: JSON.stringify({'notificationConsent': false}),
success: function (data) {
data = JSON.parse(data);
$('#notificationChecked').prop('checked', data['notificationConsent']);
},
contentType: "application/json",
dataType: 'json'
});
}
});
</script>
{% endblock %}
@@ -5,7 +5,8 @@ assetic:
filters:
cssrewrite: ~
uglifyjs2:
bin: /usr/local/bin/uglifyjs
bin: /usr/lib/node_modules/uglify-es/bin/uglifyjs
# bin: /usr/local/bin/uglifyjs2
assets:
vendors:
inputs:
@@ -25,6 +26,9 @@ assetic:
- 'js/global.js'
- 'js/register.js'
- 'js/tags.js'
- 'js/EdeclicTools.js'
- 'js/EdeclicPushAndNotificationClient.js'
company:
inputs:
- 'js/company.js'
+49 -3
View File
@@ -51,7 +51,8 @@ doctrine:
password: "%database_password%"
charset: UTF8
orm:
auto_generate_proxy_classes: "%kernel.debug%"
#auto_generate_proxy_classes: "%kernel.debug%"
auto_generate_proxy_classes: false
entity_managers:
default:
connection: default
@@ -77,6 +78,7 @@ twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
push_public_key: "%push_params.public_key%"
fairlane_cookie_consent: '@fairlane_cookie_consent.twig'
@@ -191,8 +193,12 @@ hwi_oauth:
resource_owners:
facebook:
type: facebook
# PROD
client_id: 1800752833559014
client_secret: 454de729b1e58f506f94c8b50ca5c011
client_secret: 454de729b1e58f506f94c8b50ca5c011
#DEV TT app
# client_id: 2332071840142634
# client_secret: afb8bbca72bd8c517c64f81e998e4f12
scope: "email, public_profile, user_birthday"
infos_url: "https://graph.facebook.com/me?fields=id,email,first_name,last_name,gender,birthday,picture.type(square)"
paths:
@@ -227,4 +233,44 @@ monolog:
level: debug
type: rotating_file
max_files: 15
path: '%kernel.logs_dir%/%kernel.environment%_debug.log'
path: '%kernel.logs_dir%/%kernel.environment%_debug.log'
#Api
fos_rest:
zone:
- { path: ^/api/* }
body_converter:
enabled: true
view:
formats: { json: true, xml: false, rss: false }
view_response_listener: true
mime_types:
json: ['application/json', 'application/json;version=1.0', 'application/json;version=2.0']
serializer:
serialize_null: true
format_listener:
rules:
- { path: '^/api/', priorities: ['json'], fallback_format: 'json' }
param_fetcher_listener: true
exception:
enabled: true
codes:
{ 'AppBundle\Exception\ResourceValidationException': 400 }
messages:
{ 'AppBundle\Exception\ResourceValidationException': true }
lexik_jwt_authentication:
secret_key: '%kernel.root_dir%/../app/config/jwt/private.pem' # required for token creation
public_key: '%kernel.root_dir%/../app/config/jwt/public.pem' # required for token verification
pass_phrase: 'talentstubeforever' # required for token creation, usage of an environment variable is recommended
token_ttl: 3600000
nelmio_cors:
paths:
'^/':
allow_credentials: true
allow_origin: ['*']
allow_headers: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization']
allow_methods: ['POST','GET','DELETE','PUT']
expose_headers: []
max_age: 3600000
@@ -1,6 +1,9 @@
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
<<<<<<< HEAD
=======
indexes:
tags:
types:
@@ -139,4 +142,5 @@ fos_elastica:
driver: orm
model: AppBundle\Entity\User
provider: ~
finder: ~
finder: ~
>>>>>>> origin/master
@@ -0,0 +1,54 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1B8B1CB3A64B49F820DD713907974037
0/ahxIYlJ0RiiOqRz78LbR7g+UvBC8r4RrMWFCIOuh/FPbTYyIc0VxRMObrTqvHv
B4oUMnTzHzkOimvLWncZSIA39TL2OuQMTT7g/Cp8uh7Exnf29js7Ywv8EAQA2trw
EsLXjH5St3vLhWLQdxVUBY6tWc5yuqTJ3ze9rFojiJ0mbIoeid7L8sI4mQAocfX2
2/aMWwhQX83AJaRC7liU18nZAP4gAxYjvLAaC6zj7M3wxPv1r3Ox2PuSUfYZFkYA
HbVYq6pi/Dw32CmCniufccSr2wd0f78fZdI/E20tdAviLN6awqrjM2aFgzqZ6zw/
UCD3L1hLfGxRk6uYAFgEiFQB7dT4ZzqjopKNsVuho+DTc55kmx8iPD3xXuTMbeUY
SgiV4KcGCbHRt1HGWWbJgyOkSaPQQQk5Bf63glS4nLVNqzIqzJmpVCKuwOpKCSnK
DTeWpw9MIHLHM4SD2OM8Hh8S8l6v+Y4ash6mEtUNh6a7N+TQ1vEn/wyt8wyM7/Fh
UY/97loUyu0HC2Ox89sP1y6VcNaRQlhNj9hZzLC/q5K+Z4zAQRnGPuTowZL7ztxZ
BD+MTnNZc+Akrti+3c1vAHxzuUoBd7h8NX2pnNNUY2Wme9JqfZnCx9fV4AwVOvx6
8mvTQL5YHOv8HpsGnDoOak1r+QzHM8IrL8SSrJ/DBXMIWmFefhcIDgrXZG8LV+ck
RlSuP5Lsyy3e8AQ6hrM06DXkhjGi7gCeHIHySbzw0AiFERQz0d7XgU75DL/ALPqh
0lyqlXdrx/+qqTc0wwjYIerNLNdVqN9kvLg+aqFSwZrfiZyEy6rYdUoqYXoInwle
QBt2uqcjVUhMwdQYaDWiqHidSpIMP5nuTKDm6Z8J/SLf4iy+It1qXUEcoRKhDavm
fy+dw3JvthpoNjP3Bq+moygP8J8msS5Ti3UgVug21Fsp89fmvUO8FO2JRXLXP8+U
3HG1Ij/KKk1dxC6PT7qu9gVeoKM+W8maCVV/O84Qx/N3aXY+sHm1HsSssg0cLEC7
zaEai16xhVGI8aagYwxBHVkVVXk/CBS7zq1JYBnZOIw56d1NTjvJ3YmTx619Hyek
PJuMNjGV4mM0jONzHJbI6deE2B+f1/ej1JwoeGyBhynrZjwtTCd3JAtwRK9WO1fq
owdoCAnDOV7yDcwfFEYaNV2ie/R/kQo/fIIanykQs59Op2M0yhLvmch+C3RghLVg
qfR3Jngbqjwz/uh5ZQShZtHFirdAyer/eLD0CteDt4TrAiQxiHqrEOdqwF/G/STq
+3SSkChf6uhqUUqfmJFwxaF6AiNTkdk0YyxucWY2JXYf3qyz7ADGnI/KZZ+1LchF
2bLUKjyjnFKQoaFtDd7qMGxrTD80egN/fFV4Nybt+DTsGjdUjvCFS69j+YvZ0vIP
8rZHK7etISTfiauP9SrIR9UKpNA8fGrUgJGOMo/5Wkz4YS6LmMceQkpDxj46p8Ia
Iv+pOKez6NsckP1OiDfTxLtXL1S3xQHP3V0dYI5UcWt8Bczi2VylZCcS8JiV8Cqy
+EYRaIB9Qi1X5uLQsbiyS70rJp9mJ3xUR2dIzD70njCIDtLPA2b9dXqXm1IyqdkB
46W0MOnyI699XgiywvPovwhzTH8uO5Xn5gnjEgD92pHdJ2iTVQDTC9qtKhODrhbC
ouOCbS/LPAnQMwlLD1rWAeJcBJ3PL1KdAlaxWq3Jd/iMhDh/hSboS88Lm88RYtBh
3DhMCyxY1gu6jyzuWN2pHKzCvZ1Aqqm1SMS/8nAPe/KtPJO7zTRQJIrrfPK1pt2B
u5tu1zupVKihoRkLZtV4FUwDBo8DE9V65b/LAJZtuId77ci7aWRoD5b1Lc9X9iyH
cFJTQbMxzA76/8F9/Y1h8D9mdP+N9Tfw6iOvRxszqciGAsUasqo4Xm3ZOQqCcOo5
djoywGnzqsfxrV733i2KHRqz7XUkLf8n6URloH2i1tSbHWl7fmYAC0N85IUs1PxQ
DB0LUtQgS03gjE4pRJSlgf8JX/0KrG8sYpcvz9R5CqMKrkM6rDy6ehe4P5xVQ+3m
WNCZFfGjCTcuEVLFDNx8CdF8qIV/BCcUSty7KXXoC3AMOAsVlZSwskmKN61GJmBS
Sz1bDwZO6QCZgXR2fH0UMEnCkpksS4xf3f0oq5/WzWzC4ZaDHnwt5NqKE8XXeYpn
isulqUFmCK2VhkqRX1rwND8E45yDG8+U5lyJSHp4y8Fe+AEQjxXUxXDefc80s09i
LMXM7iNUtESFge3BZvocdRrqvp21tkPElzaDoW0nMb0VoNI4Xfe113vBeBdEq0Hr
yuGvM8ZgvKjzl1T4h9PTaBu97kR1QjBSiY0PeEeSMtq/W1XbFO5jU4g/utVRluBm
z64kldtRW1RC8vosrN4sNbdVDAvL43Dynl0wYMI+jgIN3HP2QnOTDH1MLQ5BJZg4
aZFSMZ70e9kF2HXpFnfp+SsuT0lMhzZrSrLvKg0pkuD8jc7FtP/HoLcay2doBufd
fS4VheiaGm7om9Ggmkowld1CUpuzfyi7NDcymWH6J37Ypcvprn1Ts9iBcBDaOsbZ
T3pP0mU4glmRPFRq2IRZXOgTQFXIJKYFpnt0LCC2IuzbQLTKy0LVr6Ksc6ZD21j5
AR/xblSp8dZDS4ltrN44r+rtcio7dN9KlDctURpoqdw8oatwpk5QLFfYeMKPRn6j
yQA4tatWlTxr/UR8Xy8JNcJfg7JQIYjdf36atxpv5xYvnkf6Gs56xVnRthwNYawn
h44emyq/Tuflc9FZqptUDwEPKzLvH0NWxVkNvGG92H0OtES3q9OpGPTnqhIPUTme
Jrbu7knwD5sdzYRh64BhbXem8glPStYnW7B0dSdvyvGpArF1W2cKKURgnr7XokrB
DqbeSpdRf7fE5bw9jHJgcpUJOZ3o6kGA3l309Cdcbigm7gnK0KiY0y/P8MSWEu00
C4WZOFLxuaO1iVav+spACFbFkdVmLoRBPE2hFUc6BA3E/7qNHAjlVYXbUrIR3NA+
iioXf1XFM7K0LG02mMKEFSuWIpZacDyAfjHUlrid7cFBBXLk/EWcwNyGSlRdQl7w
rn7V+QfAdTxmk2FAyO80odbrdZQaBR6oLZaFgz/MzkT6dLJXwCjKG/qJrwwV/2sv
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0emZKHHTXLKphYp1XLeh
YApXdcWoZenqaFeE9pa3yzP888bsvka7t41JZy7+LOACkjnZj8VQNhMl/JIwtuv8
L276Tox94l1CeLSDvH0vxGAvCyZzpW4pgx2xAJk1xWndkEWcx/6A7/kgdePOFNJt
41JdDsefqRMlsMjw5vCxxX4V1mlebi6owKkxVBXii476xheX1M2k3cfVbC95h++h
Yd7h10DwA17SPbmIDN07QygKqRH7RGkEU5gK2Psc+NFstmYaYj4ew1NF4X9e2Erj
5M3RnYoUfkQBaigv+GSjefL6zdp+yZwjrPtZo+YDC/M1SQLEPAsoxQZvOISrLtkH
usqdvLB8rsVysZOipJyO3OClI+Vvqy9p4CggM3rHlpzMu+e+sgpZersaNxDEz/rX
J/rMXpPTfkVSRMddkQ/s0e0w4oop/tr2Zi4fYfmaJ2Ha49PFBPT7buZeyabLyAOk
utwRBkaGiUGmfVidlb0TMK2fQQOS5WottAJJOhEDzl7woCtCBgCeclsuM6v/EDd/
9KCeMcWrx7/PHBH2I8RGSfoqTKrZ8plOOPccaY2G6zZjvceExyBjewlzOm5zXI7Z
c/L5H9mghOdLjEJ+eRLZIYL9yw1LSDjY3Q0ENkxdvkMdVnZxmsf+UFMFdxBU3VjB
hqeH8T9lC2ZWC8OJ5kA4y4ECAwEAAQ==
-----END PUBLIC KEY-----
@@ -1,5 +1,6 @@
# This file is auto-generated during the composer install
parameters:
onurb_yuml.extension: jpg
mailer_transport: smtp
mailer_host: mail.gandi.net
mailer_user: noreply@talentstube.com
@@ -24,4 +25,14 @@ parameters:
media_photo_dir: '%kernel.root_dir%/../web/uploads/photos/'
elastic_host: tt-website.elasticsearch.dev
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: MgPlINZBO4yIQM8Op2QkQJZNLEuLYUkRhDsbm1a0IpE=
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU=
@@ -28,4 +28,14 @@ parameters:
elastic_host: tt-website.elasticsearch.preprod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: M2KltnIzI3K89cYz4cjlYaOQjqcGlicqKuoga6YsZcc
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BC9XGBLNGm0RWczR4IjEPWQ9_P1BmlvT-oaVgr_GJTI2OZtT85olmi3xzQhgZF4-Bi0rPafpa8vqt5pudQ4Na6w
@@ -27,4 +27,15 @@ parameters:
elastic_host: tt-website.elasticsearch.prod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: g2Yimi3AK1ppvRqwikPyTTWcEEsTdRPxoBJ2Vi9bOWw
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BG2lV673DvB67dzEwX9GKfds3sXaEdtZo2oWO1cO2xUdTJAFZ_rV_UrP1nHQz-F8LJNO9HxG0kmQRIb54JL1ZCA
@@ -38,4 +38,17 @@ parameters:
# Elastic
elastic_host: tt.search_db
elastic_port: 9200
elastic_port: 9200
#Push
push_params:
#don't forget trailing slash for dir
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='
private_key: 'MgPlINZBO4yIQM8Op2QkQJZNLEuLYUkRhDsbm1a0IpE='
service_mail_subject: 'mailto:thomas.berrod@e-declic.com'
ttl: 300
urgency: 'high'
topic: 'Emploi'
push_params.public_key: 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='
delivery_addresses: thomas.berrod@e-declic.com
@@ -20,6 +20,12 @@ hwi_oauth_connect:
hwi_oauth_redirect:
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
prefix: /login
bentools_webpush:
resource: '@WebPushBundle/Resources/config/routing.xml'
prefix: /webpush
fairlane_cookie_consent:
resource: "@FairlaneCookieConsentBundle/Resources/config/routing.yml"
resource: "@FairlaneCookieConsentBundle/Resources/config/routing.yml"
api_login_check:
path: /api/login_check
@@ -13,3 +13,7 @@ _errors:
_main:
resource: routing.yml
doctrine_yuml:
resource: "@OnurbYumlBundle/Resources/config/routing.yml"
prefix: /my_prefix/
+31 -1
View File
@@ -5,12 +5,31 @@ security:
fos_userbundle:
#id: fos_user.user_provider.username_email
id: app.user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/api/login_check
stateless: true
anonymous: true
provider: fos_userbundle
json_login:
check_path: /api/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
anonymous: true
provider: fos_userbundle
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
pattern: ^/
remember_me:
@@ -33,6 +52,8 @@ security:
anonymous: true
switch_user:
provider: fos_userbundle
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
@@ -44,6 +65,15 @@ security:
- { path: ^/talent/recherche/, roles: ROLE_COMPANY }
- { path: ^/entreprise/me/, roles: ROLE_COMPANY }
- { path: ^/territoire/me/, roles: ROLE_TERRITORY }
- { path: ^/api/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/api/login_check_oauth, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/reset_password, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/confirmAccount, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/answers, roles: IS_AUTHENTICATED_FULLY, methods: [GET]}
- { path: ^/api/answer/[0-9]+/messages, roles: IS_AUTHENTICATED_FULLY, methods: [GET]}
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY, methods: [POST, PUT, DELETE, PATCH] }
- { path: ^/api, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET]}
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
+14 -4
View File
@@ -15,9 +15,9 @@ services:
class: AppBundle\Utils\Services\AfterLoginRedirection
arguments: ['@router']
app.ad_searcher:
class: AppBundle\Utils\Services\AdSearcher
arguments: ['@fos_elastica.finder.ads.adfr']
#app.ad_searcher:
# class: AppBundle\Utils\Services\AdSearcher
# arguments: ['@fos_elastica.finder.ads.adfr']
app.ad_tags_searcher:
class: AppBundle\Utils\Services\AdSearcher
@@ -60,7 +60,7 @@ services:
class: AppBundle\Utils\Services\CompanyManager
arguments: ["@doctrine.orm.entity_manager", "@mt.slug"]
app.ad_manager:
app.ad_manager:
class: AppBundle\Utils\Services\AdManager
arguments: ["@doctrine.orm.entity_manager","@security.token_storage", "@mt.slug", "@app.mail_manager"]
@@ -83,3 +83,13 @@ services:
app.user_provider:
class: AppBundle\Security\Core\User\FOSUBUserProvider
arguments: ["@fos_user.user_manager","@doctrine.orm.entity_manager","@mt.slug","@service_container", { facebook: facebookId, linkedin: linkedinId}]
# PUSH
app.notification_sender:
class: AppBundle\Utils\Services\NotificationSender
arguments: ["@doctrine.orm.entity_manager","@fos_user.user_manager", "%push_params%"]
app.user_subscription_manager:
class: AppBundle\Utils\Services\UserSubscriptionManager
arguments: ["@doctrine.orm.entity_manager"]
app.api_key_authenticator:
class: AppBundle\Security\ApiKeyAuthenticator
+11 -4
View File
@@ -23,8 +23,8 @@
},
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.2.*",
"doctrine/orm": "2.6.*@dev",
"symfony/symfony": "^3.4",
"doctrine/orm": "^2.6.2",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3.10",
@@ -37,7 +37,6 @@
"friendsofsymfony/user-bundle": "~2.0",
"doctrine/mongodb-odm-bundle": "^3.0",
"doctrine/mongodb-odm": "^1.0",
"alcaeus/mongo-php-adapter": "^1.0",
"dunglas/doctrine-json-odm": "dev-master",
"php-ffmpeg/php-ffmpeg": "^0.5",
"requestlab/vimeo-bundle": "^0.0.3",
@@ -51,8 +50,16 @@
"symfony/assetic-bundle": "^2.8",
"friendsofsymfony/elastica-bundle": "4.1.*",
"liip/imagine-bundle": "^1.9",
"bentools/webpush-bundle": "0.3.*",
"twig/extensions": "^1.5",
"fairlane/cookie-consent-bundle": "^1.0"
"fairlane/cookie-consent-bundle": "^1.0",
"jms/serializer-bundle": "^2.4",
"friendsofsymfony/rest-bundle": "^2.4",
"white-october/pagerfanta-bundle": "^1.2",
"willdurand/hateoas-bundle": "^1.4",
"lexik/jwt-authentication-bundle": "^2.5",
"nelmio/cors-bundle": "^1.5",
"onurb/doctrine-yuml-bundle": "^1.1"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
+3267 -649
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,93 @@
<?php
namespace AppBundle\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Console\Input\InputOption;
class SendPushCommand extends ContainerAwareCommand
{
private const defaultEmail = 'thomas.berrod@e-declic.com';
protected function configure()
{
$this
->setName('app:push:send')
->setDescription('Send a push to Users by email, profile completeness, keywords matching.')
->setHelp(' ! Your user must have subscribed to push\n'.
' unless option -t, enter a .json file discribing your intent in the push dir.\n'.
' You can specify keywords OR profile completeness\n'.
' pushType can be "keyword" or "profile" or "general" or "users"\n'
)
->addArgument('email', InputArgument::OPTIONAL, 'The email of the user.')
->addOption(
'filename',
'f',
InputOption::VALUE_OPTIONAL,
'Name of file in the push directory "filename.json"',
'coriolis.json'
)
->addOption(
'test',
't',
InputOption::VALUE_NONE,
'Send a test to a defaultEmail '
)
->addOption(
'all',
'a',
InputOption::VALUE_NONE,
'Send push to all subscribed users'
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// email pour test en dev
$email = $input->getArgument('email');
if ($email == null) {
$email = self::defaultEmail;
}
$filename = $input->getOption('filename');
$testOption = $input->getOption('test');
$globalOption = $input->getOption('all');
// $style = new OutputFormatterStyle('red', 'yellow', array('bold', 'blink'));
// $output->getFormatter()->setStyle('fire', $style);
$output->writeln([
'Push Sender',
'============',
$this->getContainer()->getParameter('kernel.root_dir'),
'============',
]);
$notificationManager = $this->getContainer()->get('app.notification_sender') ; //$this->getContainer()->get('app.product_manager');
//lpio
if($testOption !== false)
{
$output->writeln('sending a test probe to user (no config used) ---> '.$email );
$notificationManager->sendTestNotification($email, $filename, $output);
}
else if ($globalOption !== false)
{
//send globaly
$output->writeln('sending to all subscriptions');
$notificationManager->sendPushToAllSubscribedUsers($filename, $output);
}
else
{
$output->writeln('sending file description '.$filename.' to user ---> '.$email );
$output->writeln('Executing NotificationSender test script');
$notificationManager->sendSingleNotification($email, $filename, $output);
}
}
}
@@ -309,8 +309,8 @@ class AdController extends Controller
} else {
$session->remove('contratSearch');
}
$adSearcher = $this->get('app.ad_searcher');
$ads = $adSearcher->process($data);
//$adSearcher = $this->get('app.ad_searcher');
$ads = array();//$adSearcher->process($data);
if(empty($ads)){
$ads = $this->getPublishedAds($promoted);
$noResults = true;
@@ -0,0 +1,119 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Ad;
use AppBundle\Representation\Ads;
use AppBundle\Representation\SingleAd;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use Symfony\Component\HttpFoundation\JsonResponse;
class AdController extends FOSRestController
{
/**
* @Rest\Get(path="/api/ads/{id}", name="api_ad_show", requirements={"id"="\d+"})
* @Rest\View
*
*/
public function showAction(Ad $ad)
{
// return $ad;
//return new SingleAd($ad);
$data = $this->get('jms_serializer')->serialize($ad, 'json', SerializationContext::create()->setGroups(array('ad_detail')));
return new JsonResponse($data, 200, [], true);
}
/**
* @Rest\Get("/api/ads", name="api_ad_list")
*
* @Rest\QueryParam(
* name="keyword",
* requirements="\w+",
* nullable=true,
* description="The keyword to search for."
* )
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* nullable=true,
* requirements="\d+",
* default="15",
* description="Max number of ads per page."
* )
* @Rest\QueryParam(
* name="offset",
* nullable=true,
* requirements="\d+",
* default="1",
* description="The pagination offset"
* )
* @Rest\QueryParam(
* name="isPromoted",
* requirements="\d+",
* nullable=true,
* description="Ads are satisfied (pourvues) or not "
* )
*
* @Rest\QueryParam(
* name="isEmphasis",
* requirements="\d+",
* nullable=true,
* description="Ads are promoted -mise en avant"
* )
*
* @Rest\QueryParam(
* name="status",
* requirements="\w+",
* nullable=true,
* description="Ads filtered by status (PUBLISHED, DISABLE, DRAFT, CLOSED, DECLINED)"
* )
*
* @Rest\View(statusCode=200, serializerGroups={"ad_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository('AppBundle:Ad')->search(
$paramFetcher->get('keyword'),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$paramFetcher->get('status'),
$paramFetcher->get('isPromoted'),
$paramFetcher->get('isEmphasis')
);
return new Ads($pager);
}
/**
* @Rest\Post("/api/ads", name="api_ad_create")
* @Rest\View(StatusCode = 201)
* @ParamConverter("ad", converter="fos_rest.request_body")
*/
public function createAction(Ad $ad)
{
$em = $this->getDoctrine()->getManager();
$em->persist($ad);
$em->flush();
return $this->view(
new SingleAd($ad),
Response::HTTP_CREATED,
['Location' => $this->generateUrl('api_ad_show', ['id' => $ad->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]
);
}
}
@@ -0,0 +1,271 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Answer;
use AppBundle\Entity\Message;
use AppBundle\Entity\Company;
use AppBundle\Entity\user;
use AppBundle\Representation\Answers;
use AppBundle\Representation\SingleAnswer;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use AppBundle\Exception\ResourceValidationException;
use AppBundle\Exception\UnknownUserException;
class AnswerController extends FOSRestController
{
/**
* @Rest\Get(path="/api/answers/{id}", name="api_answer_show", requirements={"id"="\d+"})
* @Rest\View
*
*/
public function showAction(Answer $answer)
{
$usr = $this->getUser();
$userAnswer = $this->getDoctrine()->getRepository('AppBundle:Answer')->findOneBy(array('user' => $usr, 'id' => $answer->getId()));
if ($userAnswer) {
$data = $this->get('jms_serializer')->serialize($answer, 'json', SerializationContext::create()->setGroups(array('answer_detail')));
return new JsonResponse($data, 200, [], true);
} else {
$message = 'Pas de candidature correspondante.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
}
/**
* @Rest\Get("/api/answers", name="api_answer_list")
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="15",
* description="Max number of answers per page."
* )
* @Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="1",
* description="The pagination offset"
* )
* @Rest\View(StatusCode = 200, serializerGroups={"answer_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$user = $this->getUser();
$pager = $this->getDoctrine()->getRepository('AppBundle:Answer')->search(
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$user->getId()
);
return new Answers($pager);
}
/**
* @Rest\Post("/api/answers", name="api_answer_create")
* @Rest\View(StatusCode = 201)
*/
public function createAction(Request $request)
{
$usr = $this->getUser();
if ($usr !== null) {
$answer = new Answer($usr, null, 'SENDED');
$em = $this->getDoctrine()->getManager();
$mediaId = htmlspecialchars($request->get('mediaId'));
$companyId = htmlspecialchars($request->get('companyId'));
$adId = htmlspecialchars($request->get('adId'));
if (!is_numeric($mediaId) || !is_numeric($companyId) || ($adId != null && !is_numeric($adId))) {
$message = 'Le média, l\'entreprise ou l\'offre ne sont pas au format demandé';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$existAdAnswer = null;
$existCompanyAnswer = null;
// Verify if users have already posted answers
if (isset($adId) && $adId != null) {
$existAdAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $usr, 'ad' => $adId));
} else {
$existCompanyAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $usr, 'company' => $companyId));
}
if (!isset($mediaId) || !isset($companyId) || $mediaId == null || $companyId == null) {
$message = 'Aucune vidéo ou entreprise sélectionnée.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else if ($existAdAnswer) {
$message = 'Vous avez déja postulé pour cette offre';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else if ($existCompanyAnswer) {
$message = 'Vous avez déja postulé pour cette entreprise.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else {
$video = $em->getRepository('AppBundle:Media')->find($mediaId);
$company = $em->getRepository('AppBundle:Company')->find($companyId);
// Verify if company or video exists
if (!$video || !$company) {
$message = 'Pas d\'entreprises ou de vidéos existantes';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
if (isset($adId) && $adId != null) {
$ad = $em->getRepository('AppBundle:Ad')->find($adId);
$answer->setAd($ad);
}
$answer->setVideo($video)
->setCompany($company);
$em->persist($answer);
$em->flush();
$userCompany = $company->getUsers();
$message = new Message('Candidature', 'Video', $usr, $userCompany{
0}, 'CONTACT_TALENT', $answer);
$message->setVideo($video);
$em->persist($message);
$em->flush();
$status = array('status' => "success", "idAnswer" => $answer->getId(), "idMessage" => $message->getId());
}
} else {
$message = 'Vous n\'êtes pas connecté en tant qu\'utilisateur.';
}
return new JsonResponse($status);
}
// valid request (from postman code ):
//POST /app_dev.php/api/media HTTP/1.1
// Host: localhost
// Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
// Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1NTg2MTM2NzYsImV4cCI6MTU1ODYxNzI3Niwicm9sZXMiOlsiUk9MRV9UQUxFTlQiLCJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJ0aG9tYXMuYmVycm9kQGUtZGVjbGljLmNvbSJ9.gREC7Haj2geQNn3WArAL4jhBcPI67YJuJOEYiTJ4VeJztM7TRKo8XplXXdDKRs-J_AsHIOmEYWb08AZIivNXw652Ge_9VhpvhS67xa2O30T-ZingVVofZ8Anjbgof32tVkwL2SzNd82rxw4DbFWgSE24h1tw2NO-EUnvLxD3eGUgPerdJ-g74zwJ4tv2kBI3_TaTR35x0HjPnxtihpT2FQHwR-kYQHtJb7rmR7XTloDBu-cZiiEkfgZekt2NyOvD58HcXy3hKZ09YvIFmwDnmVxOVvexVPPt8du-ozXqtt6IlXGslqTm_dX7eTNrg2uoKgliBV6AOYFFlylgIQU1-Wr6k_OCxDEscN3NkbTDVcQbE-xSE2wjFIO0Gilk-cpmW5Kx1VCtEtyscPRiYub6dXPBgObGdKGmTcYwlG3X03x9KO9oYmjVgIreZZg2WJTzwQOoU67QxhOYknPshBSm61-VaB9OwOGJG3M6FrhZR867-Rj64FEd0HWH9lMM5OO645hlDAe3lPCG6ffUBPBOjFWCGx8HPsv_PjOaMRf21UEFpVaTfAlHrKsUog5j8Qc5-OEz9vmmlog2KjWc67alEfJujnc0m3HV731IBirar5gaO360ebwUU6aSo6HSThOnwFrTxGiCd0Eqo5T5yW446HJBRhLFYiiJerJg6EbGlAM
// User-Agent: PostmanRuntime/7.13.0
// Accept: */*
// Cache-Control: no-cache
// Postman-Token: 49a92aa5-fa39-412c-bc23-9d6ae389fa1e,569d0fea-09ba-452f-9957-989fca193603
// Host: localhost
// accept-encoding: gzip, deflate
// content-length: 228
// Connection: keep-alive
// cache-control: no-cache
// Content-Disposition: form-data; name="upload"; filename="/C:/Users/Thomas/Pictures/Camera Roll/WIN_20180917_14_29_28_Pro.mp4
// ------WebKitFormBoundary7MA4YWxkTrZu0gW--
/**
* @Rest\Post("/api/media", name="api_media_upload")
* @Rest\View(StatusCode = 201)
*
*/
public function uploadAction(Request $request)
{
$usr = $this->get('security.token_storage')->getToken()->getUser();
$usr->getUsername();
$file = $request->files->get('upload');
$status = array('status' => "success", "fileUploaded" => false);
//dump($file);
// If a file was uploaded
if (!is_null($file)) {
$mediaManager = $this->get('media_manager');
$message = $mediaManager->upload(null, $file, $usr);
//dump($message);
// generate a random name for the file but keep the extension
// $filename = uniqid().".".$file->getClientOriginalExtension();
// $path = "/path/where/we/want-to-save-the-file";
// $file->move($path,$filename); // move the file to a path
$status = array('status' => "success", "fileUploaded" => true, "message" => $message);
}
return new JsonResponse($status);
}
/**
* @Rest\Post("/api/answers/message", name="api_answer_message")
* @Rest\View(StatusCode = 201)
*/
public function addMessageAction(Request $request)
{
$usr = $this->get('security.token_storage')->getToken()->getUser();
$usr->getUsername();
$em = $this->getDoctrine()->getManager();
$answerId = htmlspecialchars($request->get('answerId'));
$messageText = htmlspecialchars($request->get('message'));
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('id' => $answerId));
if (!isset($existAnswer)) {
$message = 'Aucune candidature ne correspond.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
if (!isset($messageText)) {
$message = 'Le message est vide.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$answerReceipiant = $existAnswer->getAd() !== null ? $existAnswer->getAd()->getCreator()
: $existAnswer->getCompany()->getUsers(){ 0 };
$message = new message('Chat', $messageText, $this->getUser(), $answerReceipiant, 'CHAT', $existAnswer);
$em->persist($message);
$em->flush();
$status = array('status' => "success");
return new JsonResponse($status);
}
/**
* @Rest\Get("/api/answers/{id}/messages", name="api_answer_messages", requirements={"id"="\d+"})
* @Rest\View(StatusCode = 200, serializerGroups={"answer_detail"})
*/
public function fetchMessageAction(Answer $answer)
{
$usr = $this->get('security.token_storage')->getToken()->getUser();
if ($answer->getUser()->getId() !== $usr->getId()) {
$message = "vous n'avez pas le droit de voir ce message.";
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$messages = $answer->getMessages();
//
$status = array('status' => "success", "messages" => $messages);
//
$data = $this->get('jms_serializer')->serialize(
$status,
'json',
SerializationContext::create()->setGroups(array('answer_detail'))
);
return new JsonResponse($data, 200, [], true);
}
}
@@ -0,0 +1,96 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Company;
use AppBundle\Representation\Companies;
use AppBundle\Representation\SingleCompany;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use Symfony\Component\HttpFoundation\JsonResponse;
class CompanyController extends FOSRestController
{
/**
* @Rest\Get(path="/api/companies/{id}", name="api_company_show", requirements={"id"="\d+"})
* @Rest\View
*/
public function showAction(Company $company)
{
$data = $this->get('jms_serializer')->serialize($company, 'json', SerializationContext::create()->setGroups(array('company_detail')));
return new JsonResponse($data, 200, [], true);
}
/**
* @Rest\Get("/api/companies", name="api_company_list")
* @Rest\QueryParam(
* name="keyword",
* requirements="[a-zA-Z -@$']+",
* nullable=true,
* description="The keyword to search for."
* )
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="10",
* nullable=true,
* description="Max number of companies per page."
* )
* @Rest\QueryParam(
* name="offset",
* requirements="\d+",
* nullable=true,
* default="1",
* description="The pagination offset"
* )
* @Rest\QueryParam(
* name="isEmphasis",
* requirements="\d+",
* nullable=true,
* description="Companies are promoted -mise en avant"
* )
* @Rest\View(statusCode=200, serializerGroups={"company_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository('AppBundle:Company')->search(
$paramFetcher->get('keyword'),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$paramFetcher->get('isEmphasis')
);
return new Companies($pager);
}
/**
* @Rest\Post("/api/companies", name="api_company_create")
* @Rest\View(StatusCode = 201)
* @ParamConverter("company", converter="fos_rest.request_body")
*/
public function createAction(Company $company)
{
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
return $this->view(
new SingleCompany($company),
Response::HTTP_CREATED,
['Location' => $this->generateUrl('api_company_show', ['id' => $company->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]);
}
}
@@ -0,0 +1,137 @@
<?php
/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Controller\Api;
use FOS\RestBundle\Util\ExceptionValueMap;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
/**
* Custom ExceptionController that uses the view layer and supports HTTP response status code mapping.
*/
class ExceptionController
{
/**
* @var ViewHandlerInterface
*/
private $viewHandler;
/**
* @var ExceptionValueMap
*/
private $exceptionCodes;
/**
* @var bool
*/
private $showException;
public function __construct(
ViewHandlerInterface $viewHandler,
ExceptionValueMap $exceptionCodes,
$showException
) {
$this->viewHandler = $viewHandler;
$this->exceptionCodes = $exceptionCodes;
$this->showException = $showException;
}
/**
* Converts an Exception to a Response.
*
* @param Request $request
* @param \Exception|\Throwable $exception
* @param DebugLoggerInterface|null $logger
*
* @throws \InvalidArgumentException
*
* @return Response
*/
public function showAction(Request $request, $exception, DebugLoggerInterface $logger = null)
{
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
$code = $this->getStatusCode($exception);
$templateData = $this->getTemplateData($currentContent, $code, $exception, $logger);
$view = $this->createView($exception, $code, $templateData, $request, $this->showException);
$response = $this->viewHandler->handle($view);
return $response;
}
/**
* @param \Exception $exception
* @param int $code
* @param array $templateData
* @param Request $request
* @param bool $showException
*
* @return View
*/
protected function createView(\Exception $exception, $code, array $templateData, Request $request, $showException)
{
$view = new View($exception, $code, $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : []);
$view->setTemplateVar('raw_exception');
$view->setTemplateData($templateData);
return $view;
}
/**
* Determines the status code to use for the response.
*
* @param \Exception $exception
*
* @return int
*/
protected function getStatusCode(\Exception $exception)
{
// If matched
if ($statusCode = $this->exceptionCodes->resolveException($exception)) {
return $statusCode;
}
// Otherwise, default
if ($exception instanceof HttpExceptionInterface) {
return $exception->getStatusCode();
}
return 500;
}
/**
* Determines the template parameters to pass to the view layer.
*
* @param string $currentContent
* @param int $code
* @param \Exception $exception
* @param DebugLoggerInterface $logger
*
* @return array
*/
private function getTemplateData($currentContent, $code, \Exception $exception, DebugLoggerInterface $logger = null)
{
return [
'exception' => FlattenException::create($exception),
'status' => 'error',
'status_code' => $code,
'status_text' => array_key_exists($code, Response::$statusTexts) ? Response::$statusTexts[$code] : 'error',
'currentContent' => $currentContent,
'logger' => $logger,
];
}
/**
* Gets and cleans any content that was already outputted.
*
* This code comes from Symfony and should be synchronized on a regular basis
* see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
*
* @return string
*/
private function getAndCleanOutputBuffering($startObLevel)
{
if (ob_get_level() <= $startObLevel) {
return '';
}
Response::closeOutputBuffers($startObLevel + 1, true);
return ob_get_clean();
}
}
@@ -0,0 +1,522 @@
<?php
namespace AppBundle\Controller\Api;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Model\UserInterface;
use AppBundle\Entity\Company;
use AppBundle\Exception\ResourceValidationException;
class SecurityController extends FOSRestController
{
/**
* @Rest\Post(path="/api/confirmAccount", name="api_confirm_account")
* @Rest\View
*/
public function ConfirmAccount(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$email = $request->get('email');
$confirmationToken = $request->get('confirmationToken');
if (!isset($email) || !isset($confirmationToken))
$status = array('status' => "failure", 'message' => "Paramètres invalides.");
else {
$user = $userManager->findUserByConfirmationToken($confirmationToken);
if (isset($user)) {
if ($user->getEmail() !== $email)
$status = array('status' => "failure", 'message' => "Aucune confirmation effectuée. NB: Tentative de corruption !", "email" => $user->getEmail());
else {
$user->setConfirmationToken(null);
$user->setEnabled(true);
$userManager->updateUser($user);
$status = array('status' => "success");
}
} else {
$status = array('status' => "failure", 'message' => "Aucune confirmation effectuée.");
}
}
return new JsonResponse($status);
}
/**
* @Rest\Post(path="/api/register", name="api_register")
* @Rest\View
*/
public function Register(Request $request)
{
$firstname = htmlspecialchars($request->get('firstname'));
$lastname = htmlspecialchars($request->get('lastname'));
$email = htmlspecialchars($request->get('email'));
$password = htmlspecialchars($request->get('password'));
if (!isset($firstname) || !isset($lastname) || !isset($email) || !isset($password))
$status = array('status' => "failure", 'message' => 'empty parameters');
else {
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByEmail($email);
if (isset($user))
$status = array('status' => "failure", 'message' => "L'utilisateur existe déjà.");
else {
$user = $userManager->createUser();
$user->setUsername($firstname . "-" . $lastname);
$user->setFirstname($firstname);
$user->setLastname($lastname);
$user->setEmail($email);
$user->setPlainPassword($password);
$user->setEnabled(false);
$user->setRoles(array('ROLE_TALENT'));
$tokengen = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokengen->generateToken());
$userManager->updateUser($user);
if ($user->getCompany() == null) {
$company = new Company();
$slugService = $this->get('mt.slug');
$alias = $slugService->slugify($user->getId() . "-" . $user->getFirstname() . "-" . $user->getLastname());
$company->setAlias($alias);
$company->setType("TALENT");
$user->setCompany($company);
$userManager->updateUser($user);
}
// $userManager->updatePassword($user);//pas besoin car fait dans updateUser , vraiment bizarre....
$status = array('status' => "success", 'confirmationToken' => $user->getConfirmationToken(), 'email' => $user->getEmail(), 'firstname' => $user->getFirstname(), 'lastname' => $user->getLastname());
}
}
return new JsonResponse($status);
}
/**
* @Rest\post(path="/api/update_user", name="api_update_user")
* @Rest\View
*/
public function UpdateUser(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$usr = $this->getUser();
if ($usr !== null){
$newLastName = htmlspecialchars($request->request->get('lastname'));
$newFirstName = htmlspecialchars($request->request->get('firstname'));
if (!isset($newLastName) || !isset($newFirstName) || $newLastName == null || $newFirstName == null){
$message = 'Vous devez rentrer votre nom et votre prénom pour continuer';
throw new ResourceValidationException($message,'');
} else {
$file = $request->files->get('file');
$usr->setLastName($newLastName);
$usr->setFirstName($newFirstName);
$usr->setFile($file);
$usr->upload();
$userManager->updateUser($usr);
$status = array('status' => "success", 'file' => $usr->getFile(), 'id' => $usr->getId());
}
} else {
$status = array('status' => "failure", 'message' => "Vous n'êtes pas connecté.");
}
return new JsonResponse($status);
}
/**
* @Rest\post(path="/api/reset_password", name="reset_password")
* @Rest\View
*/
public function ResetPassword(Request $request)
{
$email = $request->request->get('username');
$user = $this->get('fos_user.user_manager')->findUserByEmail($email);
if (null === $user) {
throw $this->createNotFoundException();
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
throw new ResourceValidationException('Password request allready requested', "failure", 500);
}
if (null === $user->getConfirmationToken()) {
/** @var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$this->get('fos_user.user_manager')->updateUser($user);
$status = array('status' => "success");
return new JsonResponse($status);
}
/**
* @Rest\get(path="/api/user", name="api_user")
* @Rest\View
*/
public function FetchUser(Request $request)
{
$usr = $this->getUser();
if ($usr !== null)
$status = array('status' => "success", 'user' => $usr->getIdCard());
else
$status = array('status' => "failure", 'user' => null);
return new JsonResponse($status);
}
/**
* @Rest\Post(path="/api/login_check_oauth", name="api_oauth_login")
* @Rest\View
*/
public function OAuthLoginAction(Request $request)
{
$jwtManager = $this->container->get('lexik_jwt_authentication.jwt_manager');
$token = $request->get('oauth-token');
$type = $request->get('oauth-type');
if ($type == "facebook") {
$user = $this->getOrCreateTTUserWithFacebookAccessToken($token);
} else if ($type == "linkedin") {
$user = $this->getOrCreateTTUserWithLinkedInAccessToken($token);
}
return new JsonResponse(['token' => $jwtManager->create($user)]);
}
private function getOrCreateTTUserWithFacebookAccessToken($token)
{
$em = $this->getDoctrine()->getManager();
//verify access token a facebook endpoint
// https://graph.facebook.com/debug_token?
// input_token=EAAhJAcmfVSoBAFESNEQPJFv4fOqY5G6pSUwU3BOVzmhfoP9DTu827RUelrUQHFJshZBHsHZAlZA22MvfZArsZAlJBvZBWgbuJAJQjbMcgr9dwtHZBWZCI61nsvSBbsjiA8RgonGu0zcMD8GZCJDoZA26fZAgmURRgJUprfZCOvEzZBFgfUo1UjIHhiqey&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12
$req = 'https://graph.facebook.com/debug_token?input_token=' . ($token) . '&access_token=1800752833559014|454de729b1e58f506f94c8b50ca5c011';//PROD PREPROD
//'&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12'; //DEV
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $req,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: graph.facebook.com",
// "Postman-Token: a81ddeb6-2c8c-462a-ae2d-958821c48ed2,04c50334-5c3c-4a1e-a988-d613ddd06656",
// "User-Agent: PostmanRuntime/7.13.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
//dump($response);
if ($err) {
//TODO:
// dump("cURL Error #:" . $err);
}
$data = json_decode($response);
//dump($data);
//dump($data->data->user_id);
//retreive user in our database
$user = $em->getRepository('AppBundle:User')->findOneByFacebookId($data->data->user_id);
if ($user === null) {
//try find one by tenants email
$user = $this->findUserWithFacebookEmailAndAttach($data->data, $token);
//create new user
if ($user === null) {
$user = $this->createTTUserFromOauth($data->data, 'facebook', $token);
}
}
//TODO: catch
//dump($user);
return $user;
}
private function getOrCreateTTUserWithLinkedInAccessToken($token)
{
$em = $this->getDoctrine()->getManager();
//$req = 'https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,headline,picture-url,location,industry,current-share,num-connections,summary,specialties,positions)?format=json&oauth2_access_token=' . ($token);
//dump($req);
$reqMe = 'https://api.linkedin.com/v2/me?oauth2_access_token=' . $token;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $reqMe,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: api.linkedin.com",
"User-Agent: PostmanRuntime/7.15.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
//TODO: log ??
//dump("cURL Error #:" . $err);
}
$data = json_decode($response);
//dump($data);
//dump($data->data->user_id);
//retreive user in our database
$user = $em->getRepository('AppBundle:User')->findOneByLinkedinId($data->id);
if ($user === null) {
$email = $this->requestLinkedInEmail($token);
$data->emailAddress = $email;
//try find one by tenants email and attach it
$user = $this->findUserWithLinkedInEmailAndAttach($data);
//create a new user
if ($user === null)
$user = $this->createTTUserFromOauth($data, 'linkedin',$token);
}
//TODO : catch
return $user;
}
private function requestLinkedInEmail($token)
{
$reqEmail = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))&oauth2_access_token=' . $token;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $reqEmail,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: api.linkedin.com",
"User-Agent: PostmanRuntime/7.15.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
//TODO: log ??
//dump("cURL Error #:" . $err);
}
$data = json_decode($response);
return $data->elements[0]->{'handle~'}->emailAddress;
}
private function findUserWithLinkedInEmailAndAttach($data)
{
$userManager = $this->get('fos_user.user_manager');
if (isset($data->emailAddress))
$userEmail = $data->emailAddress;
else
return null;
$user = $userManager->findUserByEmail($userEmail);
if($user == null)
return null;
$user->setLinkedinId($data->id);
$userManager->updateUser($user);
return $user;
}
private function findUserWithFacebookEmailAndAttach($data, $user_access_token)
{
$userManager = $this->get('fos_user.user_manager');
$profile = $this->getFacebookProfile($data->user_id, $user_access_token);
if (isset($profile->email)) {
$userEmail = $profile->email;
} else {
$userEmail = null;
return null;
}
$user = $userManager->findUserByEmail($userEmail);
if($user == null)
return null;
$user->setFacebookId($data->user_id);
$userManager->updateUser($user);
return $user;
}
private function createTTUserFromOauth($data, $tenant, $token)
{
$userManager = $this->get('fos_user.user_manager');
if ($tenant == 'facebook') {
$profile = $this->getFacebookProfile($data->user_id, $token);
//TODO : photo facebook
// $userPhoto = 'https://graph.facebook.com/' . $data->user_id . '/picture?height=200'. '&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12';
$userPhoto='';
if (isset($profile->birthday)) {
$birthday = \DateTime::createFromFormat('m/d/Y', $profile->birthday);
} else {
$birthday = null;
}
if (isset($profile->gender)) {
$gender = $profile->gender;
} else {
$gender = null;
}
if (isset($profile->email)) {
$userEmail = $profile->email;
} else {
$userEmail = null;
}
$id = $profile->id;
$firstname = $profile->first_name;
$lastname = $profile->last_name;
}
if ($tenant == 'linkedin') {
//TODO
$id = $data->id;
$birthday = null;
$gender = null;
if (isset($data->pictureUrl)) {
$userPhoto = $data->pictureUrl;
} else {
$userPhoto = null;
}
$userEmail = $data->emailAddress;
$firstname = $data->localizedFirstName;
$lastname = $data->localizedLastName;
}
$user = $userManager->createUser();
$user->setUsername($firstname . "-" . $lastname);
$user->setFirstname($firstname);
$user->setLastname($lastname);
$user->setEmail($userEmail);
$user->setPlainPassword(uniqid());
$user->setEnabled(true);
$user->setSocialPicture($userPhoto);
$user->setRoles(array('ROLE_TALENT'));
$user->setBirthday($birthday);
$user->setGender($gender);
if ($tenant == "linkedin") {
$user->setLinkedinId($id);
}
if ($tenant == "facebook") {
$user->setFacebookId($id);
}
$userManager->updateUser($user);
if ($user->getCompany() == null) {
$company = new Company();
$slugService = $this->get('mt.slug');
$alias = $slugService->slugify($user->getId() . "-" . $user->getFirstname() . "-" . $user->getLastname());
$company->setAlias($alias);
$company->setType("TALENT");
$user->setCompany($company);
$userManager->updateUser($user);
}
$token = new UsernamePasswordToken($user, null, "main", $user->getRoles());
$this->container->get("security.token_storage")->setToken($token);
return $user;
}
private function getFacebookProfile($user_id, $user_access_token)
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://graph.facebook.com/" . $user_id . "?fields=id,name,gender,birthday,first_name,last_name,email" . "&access_token=" . $user_access_token,
// '&access_token=1800752833559014|454de729b1e58f506f94c8b50ca5c011',//PROD PREPROD
// "&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12", //DEV
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: graph.facebook.com",
//"Postman-Token: e0ab326f-4916-4c8b-80a1-bd082ce6e6a2,f972ce2f-f209-4f60-84cd-e04099e8e43d",
"User-Agent: PostmanRuntime/7.13.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
//echo $response;
}
$data = json_decode($response);
return $data;
}
}
@@ -1,11 +1,9 @@
<?php
namespace AppBundle\Controller;
use AppBundle\Form\AdSearchType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
@@ -98,4 +96,5 @@ class DefaultController extends Controller
//return $this->render('page_static/video_territoire.html.twig');
return $this->render('page_static/accompagnement_video_territoire.html.twig');
}
}
@@ -0,0 +1,73 @@
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use BenTools\WebPushBundle\Registry\WebPushManagerRegistry;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\User\UserInterface;
class PushController extends Controller
{
/**
* @Route("/push/save-subscription/", name="save-subscription")
*/
public function saveSubscription(Request $request)
{
//Sample Request
// {
// "endpoint":"https://fcm.googleapis.com/fcm/send/cUugkgI46DE:APA91bEUZ-AN2BfyEmxNilWKdg1qUZObgQ1Q_T1cWxM2ECqdH00AyXYt1R4snPkX12s4-38_LWF3Yrx6xcXYna0lUsL9ImBTrxjJHzv9SLTXrJI4f0omqf285fOZ8oeo50jqKB6rNiOF",
// "expirationTime":null,
// "keys":{
// "p256dh":"BPprM2eUBJR85AkTlYaryaByeF3TKYEJ-VyZcdgx51SyijfyLgohFYK0fM9HZoAUIwwUx-_LtthqNGZDVxcx-uo",
// "auth":"YtUnqHo0RTsBn7B_BaFT8Q"}
// }
$user = $this->getUser();
// if (!$user) {
// throw new BadRequestHttpException("User is not logged in.");
// }
$subscription = json_decode($request->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new BadRequestHttpException(json_last_error_msg());
}
if (!isset($subscription['endpoint'])) {
throw new BadRequestHttpException('Invalid subscription object.');
}
// if (!$user instanceof UserInterface) {
// throw new \RuntimeException('This bundle only works with user object that implement ' . UserInterface::class);
// }
$manager = $this->container->get("app.user_subscription_manager");
$subscriptionHash = $manager->hash($subscription['endpoint']);
$userSubscription = $manager->getUserSubscription($user, $subscriptionHash)
or $userSubscription = $manager->factory($user, $subscriptionHash, $subscription);
$manager->save($userSubscription);
return new JsonResponse(array('success' => true),200);
}
/**
* @Route("/push/delete-subscription/", name="delete-subscription")
*/
public function unsubscribeUser(Request $request)
{
$subscription = json_decode($request->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new BadRequestHttpException(json_last_error_msg());
}
if (!isset($subscription['endpoint'])) {
throw new BadRequestHttpException('Invalid subscription object.');
}
$manager = $this->container->get("app.user_subscription_manager");
$subscriptionHash = $manager->hash($subscription['endpoint']);
$userSubscription = $this->manager->findByHash($subscriptionHash);
if(!empty($userSubscription))
$manager->delete($userSubscription[0]);
return new JsonResponse(array('success' => true),200);
}
}
@@ -174,17 +174,52 @@ class TalentController extends Controller
{
$userManager = $this->get('fos_user.user_manager');
$user = $this->getUser();
$formFactory = $this->container->get('fos_user.change_password.form.factory');
$formPw = $formFactory->createForm();
$formPw->setData($user);
if ($formPw->isSubmitted() && $formPw->isValid()) {
$userManager->updateUser($user);
}
$manager = $this->container->get("app.user_subscription_manager");
$subscriptions = $manager->findByUser($user);
$isNotificationAllowed = !empty($subscriptions);
return $this->render('talent/my_account.html.twig', [
'formPw' => $formPw->createView(),
'isNotificationAllowed' => $isNotificationAllowed
]);
}
/**
* @Route("/talent/me/notificationConsent", name="talent_notification_consent")
*/
public function notificationConsent(Request $request)
{
$data = json_decode($request->getContent(), true);
$consent = $data["notificationConsent"];
if($consent === false)
{
//delete all existing user_subscription
$user = $this->getUser();
$manager = $this->container->get("app.user_subscription_manager");
$subscriptions = $manager->findByUser($user);
foreach ($subscriptions as $key => $value) {
$manager->delete($value);
}
}
$encode = array('notificationConsent' => $consent);
return new JsonResponse(json_encode($encode));
}
/**
* @Route("/talent/me/espace-oe", name="talent_ad_space")
*/
@@ -8,6 +8,11 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;
use Hateoas\Configuration\Annotation as Hateoas;
/**
* Ad
@@ -15,6 +20,26 @@ use Symfony\Component\Validator\Constraints as Assert;
* @ORM\Table(name="ad")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AdRepository")
* @ORM\HasLifecycleCallbacks()
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_ad_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
* @Hateoas\Relation(
* "company",
* embedded = @Hateoas\Embedded("expr(object.getCompany())")
* )
*
* @Hateoas\Relation(
* "creator",
* embedded = @Hateoas\Embedded("expr(object.getCreator())")
* )
*/
class Ad
{
@@ -30,6 +55,9 @@ class Ad
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
* @Type("integer")
*/
private $id;
@@ -37,6 +65,7 @@ class Ad
* @var string
*
* @ORM\Column(name="reference", type="string", length=255)
*
*/
private $reference;
@@ -51,6 +80,8 @@ class Ad
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
*/
private $title;
@@ -65,6 +96,8 @@ class Ad
* @var string
*
* @ORM\Column(name="description", type="text", nullable=true)
*
* @Groups({"ad_detail", "answer_detail"})
*/
private $description;
@@ -94,6 +127,8 @@ class Ad
* @var boolean
*
* @ORM\Column(name="is_promoted", type="boolean", nullable=true, options={"comment":"Peux t'on répondre"})
*
* @Groups({"ad_detail" ,"company_detail", "ad_list"})
*/
private $isPromoted;
@@ -108,6 +143,7 @@ class Ad
* @var boolean
*
* @ORM\Column(name="is_answerable", type="boolean", nullable=true, options={"comment":"Annonce promu ?"})
* @Groups({"company_detail"})
*/
private $isAnswerable;
@@ -115,6 +151,7 @@ class Ad
* @var integer
*
* @ORM\Column(name="defcon", type="smallint", nullable=true, options={"comment":"Etat d'alerte de modération"})
*
*/
private $defcon;
@@ -122,6 +159,8 @@ class Ad
* @var array
*
* @ORM\Column(name="public_tag", type="json_document", nullable=true, options={"jsonb":true})
*
*
*/
private $publicTag;
@@ -136,6 +175,9 @@ class Ad
* @var array
*
* @ORM\Column(name="extra", type="json_document", nullable=true, options={"jsonb":true})
*
* @Groups({"ad_detail", "ad_list", "answer_detail", "company_detail"})
*
*/
private $extra;
@@ -143,21 +185,29 @@ class Ad
* @var array
*
* @ORM\Column(name="location", type="json_document", nullable=true, options={"jsonb":true})
*
* @Groups({"ad_detail", "ad_list","answer_detail", "company_detail"})
*/
private $location;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="ads", cascade={"persist"})
*
* @Groups({"ad_detail", "ad_list", "company_detail", "answer_list", "answer_detail"})
*
*/
private $video;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="ads")
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="ads")
*
*/
private $creator;
@@ -165,6 +215,8 @@ class Ad
* @var string
*
* @ORM\Column(name="emphasis", type="boolean", options={"comment":"A la une"}, nullable=true)
*
* @Groups({"company_list"})
*/
private $emphasis;
@@ -7,6 +7,11 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Criteria as Criteria;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Accessor;
/**
* Answer
@@ -14,6 +19,32 @@ use Doctrine\Common\Collections\Criteria as Criteria;
* @ORM\Table(name="answer")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AnswerRepository")
* @ORM\HasLifecycleCallbacks()
*
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_answer_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
* @Hateoas\Relation(
* "ad",
* embedded = @Hateoas\Embedded("expr(object.getAd())")
* )
*
* @Hateoas\Relation(
* "user",
* embedded = @Hateoas\Embedded("expr(object.getUser())")
* )
*
* @Hateoas\Relation(
* "company",
* embedded = @Hateoas\Embedded("expr(object.getCompany())")
* )
*/
class Answer
{
@@ -28,28 +59,34 @@ class Answer
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"answer_list", "answer_detail"})
*
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ad", inversedBy="answers")
* @ORM\JoinColumn(nullable=true)
* @Groups({"answer_list", "answer_detail"})
*/
private $ad;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="spontaneousApplications")
* @ORM\JoinColumn(nullable=true)
* @Groups({"answer_list", "answer_detail"})
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $video;
@@ -57,6 +94,7 @@ class Answer
* @var int
*
* @ORM\Column(name="vote", type="smallint", nullable=true)
*
*/
private $vote;
@@ -64,6 +102,7 @@ class Answer
* @var string
*
* @ORM\Column(name="comment", type="text", nullable=true)
* @Groups({"answer_detail","answer_list"})
*/
private $comment;
@@ -71,6 +110,7 @@ class Answer
* @var \DateTime $sendTime
*
* @ORM\Column(name="send_time", type="datetime", nullable=true)
* @Groups({"answer_detail","answer_list"})
*/
private $sendTime;
@@ -86,6 +126,7 @@ class Answer
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message", mappedBy="answer", cascade={"persist", "remove"})
* @ORM\OrderBy({"uTime" = "DESC"})
* @Groups({"answer_detail","answer_list"})
*/
private $messages;
@@ -8,7 +8,13 @@ use AppBundle\Utils\Traits\IsVisibleTrait;
use AppBundle\Utils\Traits\TagsJsonTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\Type;
/**
* Company
@@ -16,6 +22,17 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
* @ORM\Table(name="company")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
* @ORM\HasLifecycleCallbacks()
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_company_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
*/
class Company
{
@@ -32,6 +49,9 @@ class Company
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({ "ad_detail", "company_list", "company_detail", "answer_list"})
* @Type("integer")
*/
private $id;
@@ -39,6 +59,8 @@ class Company
* @var string
*
* @ORM\Column(name="brand_name", type="string", length=255, options={"comment":"Nom commercial"}, nullable=true)
*
* @Groups({"ad_detail", "company_list", "company_detail", "answer_list", "answer_detail"})
*/
private $brandName;
@@ -46,6 +68,9 @@ class Company
* @var string
*
* @ORM\Column(name="business_name", type="string", length=255, options={"comment":"Raison sociale"}, nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail","answer_detail","answer_list"})
*
*/
private $businessName;
@@ -53,6 +78,7 @@ class Company
* @var text
*
* @ORM\Column(name="description", type="text", length=255, nullable=true)
* @Groups({"company_detail"})
*/
private $description;
@@ -67,6 +93,8 @@ class Company
* @var string
*
* @ORM\Column(name="logo", type="string", nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail", "answer_detail","answer_list"})
*/
private $logo;
@@ -74,6 +102,8 @@ class Company
* @var string
*
* @ORM\Column(name="website", type="string", nullable=true)
*
* @Groups({"company_detail"})
*/
private $website;
@@ -87,6 +117,7 @@ class Company
/**
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Media", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="presentation_video_id", nullable=true)
* @Groups({"ad_detail", "company_detail", "company_list","answer_detail","answer_list"})
*/
private $presentationVideo;
@@ -143,6 +174,7 @@ class Company
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="company", cascade={"persist", "remove"})
* @Groups({"company_detail", "company_list"})
*/
private $ads;
@@ -153,14 +185,25 @@ class Company
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="company", cascade={"persist", "remove"})
* @Groups({"company_detail"})
*/
private $territories;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer",mappedBy="company", cascade={"persist", "remove"})
*
* @Groups({"company_detail", "company_list"})
*/
private $spontaneousApplications;
/**
* @Groups({"company_detail", "company_list"})
* @Accessor(getter="getCountPublishedAds")
*
* @Groups({"ad_list", "company_list", "company_detail"})
*/
private $countAds;
/***********************
* Constructor
***********************/
@@ -277,6 +320,46 @@ class Company
return $this->users->first();
}
/**
* @return int
*
* Return a percentage
*/
public function getCompanyCompleteness()
{
$total=9;
$empty=0;
if (empty($this->brandName))
$empty++;
if (empty($this->businessName))
$empty++;
if (empty($this->description))
$empty++;
if (empty($this->logo))
$empty++;
if (empty($this->website))
$empty++;
if (empty($this->alias))
$empty++;
if (empty($this->publicTag))
$empty++;
if ($this->presentation_video === null)
$empty++;
if (is_array($this->ad) && empty($this->ad))
$empty++;
return ($empty/$total) * 100;
}
/***********************
* Getter & Setters
***********************/
@@ -834,4 +917,16 @@ class Company
{
return $this->isPrivate;
}
/**
* Get countAds.
*
* @return int|null
*/
public function getCountPublishedAds()
{
return count($this->getPublishedAds());
}
}
@@ -6,6 +6,7 @@ use AppBundle\Utils\Traits\IsVisibleTrait;
use AppBundle\Utils\Traits\ModerationTrait;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -29,6 +30,9 @@ class Media
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"ad_detail", "company_list", "answer_detail"})
*
*/
private $id;
@@ -36,6 +40,8 @@ class Media
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
* @Groups({"ad_detail", "answer_detail"})
*
*/
private $title;
@@ -50,6 +56,8 @@ class Media
* @var string
*
* @ORM\Column(name="cdn_url", type="string", length=255)
*
* @Groups({"ad_detail", "company_detail", "company_list", "answer_detail"})
*/
private $cdnUrl;
@@ -57,6 +65,7 @@ class Media
* @var string
*
* @ORM\Column(name="metadata", type="text")
*
*/
private $metadata;
@@ -78,6 +87,8 @@ class Media
* @var array
*
* @ORM\Column(name="thumbnails", type="json_document", nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail", "answer_list"})
*/
private $thumbnails;
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -24,6 +25,7 @@ class Message
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"answer_detail","answer_list"})
*/
private $id;
@@ -31,6 +33,7 @@ class Message
* @var string
*
* @ORM\Column(name="subject", type="text")
* @Groups({"answer_detail","answer_list"})
*/
private $subject;
@@ -38,16 +41,19 @@ class Message
* @var string
*
* @ORM\Column(name="content", type="text")
* @Groups({"answer_list","answer_detail","answer_list"})
*/
private $content;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="sendedMessages", cascade={"persist"})
* @Groups({"answer_list","answer_detail","answer_list"})
*/
private $sender;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="receivedMessages", cascade={"persist"})
* @Groups({"answer_detail","answer_list"})
*/
private $recipient;
@@ -59,6 +65,7 @@ class Message
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $video;
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -7,6 +7,8 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
/**
* Recommendation
*
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\IsVisibleTrait;
use AppBundle\Utils\Traits\StatusTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
/**
* Territory Ad
@@ -23,12 +24,14 @@ class TerritoryAd
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"company_detail"})
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="territoryAds")
* @ORM\JoinColumn(nullable=false)
* @Groups({"company_detail"})
*/
private $territory;
@@ -6,10 +6,21 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\HttpFoundation\File\UploadedFile;
<<<<<<< HEAD
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;
=======
use AppBundle\Utils\Traits\CareerJsonTrait;
>>>>>>> origin/master
/**
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Table(name="fos_user")
*
* @ExclusionPolicy("all")
*/
class User extends BaseUser
{
@@ -17,6 +28,7 @@ class User extends BaseUser
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @Type("integer")
*/
protected $id;
@@ -24,6 +36,8 @@ class User extends BaseUser
* @var string
*
* @ORM\Column(name="firstname", type="string", length=255, nullable=true)
* @Expose
* @Groups({"answer_detail"})
*/
private $firstname;
@@ -31,6 +45,8 @@ class User extends BaseUser
* @var string
*
* @ORM\Column(name="lastname", type="string", length=255, nullable=true)
* @Expose
* @Groups({"answer_detail"})
*/
private $lastname;
@@ -38,6 +54,7 @@ class User extends BaseUser
* @var \DateTime
*
* @ORM\Column(name="birthday", type="datetime", length=255, nullable=true)
* @Expose
*/
private $birthday;
@@ -52,6 +69,7 @@ class User extends BaseUser
* @var string
*
* @ORM\Column(name="gender", type="string", length=255, nullable=true)
* @Expose
*/
private $gender;
@@ -212,7 +230,6 @@ class User extends BaseUser
$name = md5(uniqid()) . '.' . $this->file->guessExtension();
$this->file->move($this->getUploadRootDir(), $name);
$this->photo = $name;
}
public function getUploadDir()
@@ -312,6 +329,56 @@ class User extends BaseUser
return $this;
}
/**
* @return int
*
* Return a percentage
*/
public function getUserCompleteness()
{
$total = 6;
$empty = 0;
if (empty($this->firstname))
$empty++;
if (empty($this->lastname))
$empty++;
if (empty($this->birthday))
$empty++;
if (empty($this->photo))
$empty++;
if (empty($this->gender))
$empty++;
if (empty($this->status))
$empty++;
return ($empty / $total) * 100;
}
/**
* @return int
*
* Return a small description of the user
* used in REST services
*/
public function getIdCard()
{
$card = array(
"firstname" => $this->getFirstname(),
"lastname" => $this->getLastname(),
"email" => $this->getEmail(),
"picture" => $this->getPhoto(),
"socialPicture" => $this->getSocialPicture()
);
return $card;
}
/***********************
* Getters & Setters
***********************/
@@ -0,0 +1,161 @@
<?php
# src/AppBundle/Entity/UserSubscription.php
namespace AppBundle\Entity;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Entity()
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserSubscriptionRepository")
*/
class UserSubscription implements UserSubscriptionInterface
{
/**
* @var int
*
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @var User
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* @ORM\JoinColumn(nullable=true)
*/
private $user;
/**
* @var string
*
* @ORM\Column(type="string")
*/
private $subscriptionHash;
/**
* @var array
*
* @ORM\Column(type="json")
*/
private $subscription;
/**
* UserSubscription constructor.
* @param User $user
* @param string $subscriptionHash
* @param array $subscription
*/
public function __construct(?User $user, string $subscriptionHash, array $subscription)
{
$this->user = $user;
$this->subscriptionHash = $subscriptionHash;
$this->subscription = $subscription;
}
/**
* @return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @inheritDoc
*/
public function getUser(): UserInterface
{
return $this->user;
}
/**
* @inheritDoc
*/
public function getSubscriptionHash(): string
{
return $this->subscriptionHash;
}
/**
* @inheritDoc
*/
public function getEndpoint(): string
{
return $this->subscription['endpoint'] ?? null;
}
/**
* @inheritDoc
*/
public function getPublicKey(): string
{
return $this->subscription['keys']['p256dh'] ?? null;
}
/**
* @inheritDoc
*/
public function getAuthToken(): string
{
return $this->subscription['keys']['auth'] ?? null;
}
/**
* Set subscriptionHash.
*
* @param string $subscriptionHash
*
* @return UserSubscription
*/
public function setSubscriptionHash($subscriptionHash)
{
$this->subscriptionHash = $subscriptionHash;
return $this;
}
/**
* Set subscription.
*
* @param json $subscription
*
* @return UserSubscription
*/
public function setSubscription($subscription)
{
$this->subscription = $subscription;
return $this;
}
/**
* Get subscription.
*
* @return json
*/
public function getSubscription()
{
return $this->subscription;
}
/**
* Set user.
*
* @param \AppBundle\Entity\User $user
*
* @return UserSubscription
*/
public function setUser(\AppBundle\Entity\User $user)
{
$this->user = $user;
return $this;
}
}
@@ -0,0 +1,16 @@
<?php
namespace AppBundle\Exception;
class ResourceValidationException extends \Exception
{
public $status;
protected $message;
protected $code;
public function __construct($message, $status, $code=400){
$this->message = $message;
$this->status = $status;
$this->code = $code;
}
}
@@ -0,0 +1,7 @@
<?php
namespace AppBundle\Exception;
class UnknownUserException extends \Exception
{
}
@@ -0,0 +1,23 @@
<?php
// src/AppBundle/Form/TaskType.php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
class NotificationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$options['data'];
$builder
->add('notifications', CheckboxType::class, array(
'label' => 'Autoriser les notifications'
));
}
}
@@ -0,0 +1,25 @@
<?php
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Pagerfanta\Pagerfanta;
use Pagerfanta\Adapter\DoctrineORMAdapter;
abstract class AbstractRepository extends EntityRepository
{
protected function paginate(QueryBuilder $qb, $limit = 20, $offset = 0)
{
if (0 == $limit || 0 == $offset) {
throw new \LogicException('$limit & $offset must be greater than 0.');
}
$pager = new Pagerfanta(new DoctrineORMAdapter($qb));
$currentPage = ceil(($offset + 1) / $limit);
$pager->setCurrentPage($currentPage);
$pager->setMaxPerPage((int) $limit);
return $pager;
}
}
@@ -2,14 +2,54 @@
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
/**
* AdRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class AdRepository extends EntityRepository
class AdRepository extends AbstractRepository
{
public function search(
$term,
$order = 'asc',
$limit = 20,
$offset = 1,
$status,
$isPromoted = false,
$isEmphasis
) {
$qb = $this
->createQueryBuilder('a')
->select('a')
->where('a.isVisible = true')
->orderBy('a.title', $order);
$qb
->andWhere('a.isPromoted = ?3')
->setParameter(3, (bool) $isPromoted);
if ($status) {
$qb
->andWhere('a.status LIKE ?1')
->setParameter(1, $status);
}
if ($term) {
$qb
->andWhere('LOWER(a.title) LIKE LOWER(?2)')
->setParameter(2, '%' . $term . '%');
}
if ($isEmphasis) {
$qb
->andWhere('a.emphasis = ?4')
->setParameter(4, (bool) $isEmphasis)
->orderBy('a.emphasisOrder', 'DESC');
}
return $this->paginate($qb, $limit, $offset);
}
}
@@ -8,9 +8,23 @@ namespace AppBundle\Repository;
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class AnswerRepository extends \Doctrine\ORM\EntityRepository
class AnswerRepository extends AbstractRepository
{
public function search($order = 'asc', $limit = 20, $offset = 0, $idUser)
{
$qb = $this
->createQueryBuilder('a')
->select(['a','m','ad'])
->leftJoin('a.messages', 'm')
->leftJoin('a.ad', 'ad')
->where('a.user = :user')
->setParameter('user', $idUser)
->orderBy('a.id', $order)
;
return $this->paginate($qb, $limit, $offset);
}
public function getAnswerByCompany($id)
{
$qb = $this
@@ -10,7 +10,7 @@ use Doctrine\ORM\EntityRepository;
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class CompanyRepository extends EntityRepository
class CompanyRepository extends AbstractRepository
{
public function getCompanySortByAds()
{
@@ -57,8 +57,6 @@ class CompanyRepository extends EntityRepository
{
$qb = $this
->createQueryBuilder('c')
//->from('AppBundle:TerritoryAd', 'a')
//->where('c.id = IDENTITY(a.territory)')
->andWhere('c.type = :type')
->setParameter(':type', "TERRITORY");
@@ -75,4 +73,44 @@ class CompanyRepository extends EntityRepository
return $qb;
}
public function search($term, $order = 'asc', $limit = 10, $offset = 1,
$isEmphasis)
{
// $qb = $this
// ->createQueryBuilder('c')
// ->select('c')
// ->leftJoin('c.ads', 'a', 'WITH', 'a.status =:status')
// ->setParameter(':status', "PUBLISHED")
// ->where("c.type = 'COMPANY'")
// ->orWhere('c.presentationVideo IS NOT NULL')
// ->orderBy('a.publishedAt', 'DESC')
// ->orderBy('c.cTime', 'DESC');
$qb = $this->createQueryBuilder('c')
->select('c')
->where("c.type = 'COMPANY'")
->leftJoin('c.ads', 'a', 'WITH', 'a.status =:status')
->setParameter(':status', "PUBLISHED")
->orderBy('a.publishedAt', 'DESC')
->orderBy('c.cTime', 'DESC');
if ($isEmphasis) {
$qb
->andWhere('c.emphasis = ?1')
->setParameter(1, (bool)$isEmphasis)
->orderBy('c.emphasisOrder', 'DESC');
}
if ($term) {
$qb->andWhere('LOWER(c.businessName) LIKE LOWER(?2)')
->setParameter(2, '%' . $term . '%');
}else
$qb->andWhere("c.businessName IS NOT NULL");
$pager = $this->paginate($qb, $limit, $offset);
return $pager;
}
}
@@ -0,0 +1,45 @@
<?php
namespace AppBundle\Repository\Query;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
class CastAs extends FunctionNode
{
/** @var \Doctrine\ORM\Query\AST\PathExpression */
protected $first;
/** @var string */
protected $second;
/**
* @param SqlWalker $sqlWalker
*
* @return string
*/
public function getSql(SqlWalker $sqlWalker)
{
return sprintf("CAST(%s AS %s)",
$this->first->dispatch($sqlWalker),
$this->second
);
}
/**
* @param Parser $parser
*
* @return void
*/
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->first = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_AS);
$parser->match(Lexer::T_IDENTIFIER);
$this->second = $parser->getLexer()->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
@@ -12,6 +12,28 @@ use Doctrine\ORM\EntityRepository;
*/
class UserRepository extends EntityRepository
{
public function findOneByFacebookId($id)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where('u.facebookId LIKE :id')
->setParameter('id', $id );
return $qb->getQuery()->getOneOrNullResult();
}
public function findOneByLinkedInId($id)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where('u.linkedinId LIKE :id')
->setParameter('id', $id );
return $qb->getQuery()->getOneOrNullResult();
}
public function findByRole($role)
{
$qb = $this->_em->createQueryBuilder();
@@ -0,0 +1,107 @@
<?php
namespace AppBundle\Repository;
/**
* BookmarkRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UserSubscriptionRepository extends \Doctrine\ORM\EntityRepository
{
public function findByEmails($emails)
{
$qb = $this->createQueryBuilder('us')
->select('us')
->leftJoin('us.user', 'u')
->where('u.email IN (:emails)')
->setParameters(array('emails' => $emails));
// ->setParameter(':emails', $emails);
//dump();
$result = $qb->getQuery()->getResult();
return $result;
}
/**
*
* SELECT num_nulls(brand_name, business_name)FROM company WHERE id = 12
*
* (SELECT string_agg(quote_ident(attname), ', ') -- column list
* FROM pg_attribute
* WHERE attrelid = 'fos_user'::regclass)
* "address, alias, brand_name, business_name, c_time, cmax, cmin, ctid, description,
* description_admin, emphasis, emphasis_order, extra, id, is_private, is_visible,
* logo, presentation_video_id, public_tag, searchable, tableoid, type, u_time, website, xmax, xmin"
*/
public function findByProfilCompleteness($completenessPercentage)
{
$config = $this->_em->getConfiguration();
$config->addCustomNumericFunction('CAST', 'AppBundle\Repository\Query\CastAs');
$qb = $this->createQueryBuilder('us');
$qb->select('us')
->leftJoin('us.user', 'u')
->innerJoin('u.company', 'c')
->where('((
CAST((
CASE WHEN u.birthday IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.email IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.firstname IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.gender IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.lastname IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.photo IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN u.username IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.addresses IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.alias IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.brandName IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.businessName IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.description IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.descriptionAdmin IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.logo IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.publicTag IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN c.website IS NOT NULL THEN 1 ELSE 0 END
) AS decimal) / 15) * 100 ) >= :percent')
->setParameters(array('percent' => $completenessPercentage));
dump($qb->getQuery()->getSql());
$result = $qb->getQuery()->getResult();
dump($result);
return $result;
}
public function findByTagMatching($tags)
{
dump($tags);
$config = $this->_em->getConfiguration();
$config->addCustomNumericFunction('CAST', 'AppBundle\Repository\Query\CastAs');
$qb = $this->createQueryBuilder('us');
$qb->select('us')
->leftJoin('us.user', 'u')
->innerJoin('u.company', 'c');
$i = 0;
foreach ($tags as $tag) {
if ($i == 0) {
$i = 1;
$qb->where('CAST(c.publicTag AS text) LIKE \'%' . $tag . '%\'');
} else {
$qb->orWhere('CAST(c.publicTag AS text) LIKE \'%' . $tag . '%\'');
}
}
dump($qb->getQuery()->getSql());
$result = $qb->getQuery()->getResult();
dump($result);
return $result;
}
}
@@ -0,0 +1,56 @@
<?php
namespace AppBundle\Representation;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Pagerfanta\Pagerfanta;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*
*/
class Ads
{
/**
* @Type("array<AppBundle\Entity\Ad>")
* @Groups("ad_list")
*/
public $data;
/**
*
* @Groups("ad_list")
*/
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data;
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
@@ -0,0 +1,52 @@
<?php
namespace AppBundle\Representation;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Groups;
use Pagerfanta\Pagerfanta;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*/
class Answers
{
/**
* @Type("array<AppBundle\Entity\Answer>")
* @Groups("answer_list")
*/
public $data;
/**
*
* @Groups("answer_list")
*/
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data;
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
@@ -0,0 +1,52 @@
<?php
namespace AppBundle\Representation;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Groups;
use Pagerfanta\Pagerfanta;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*/
class Companies
{
/**
* @Type("array<AppBundle\Entity\Company>")
* @Groups("company_list")
*/
public $data;
/**
*
* @Groups("company_list")
*/
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data;
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
@@ -0,0 +1,27 @@
<?php
namespace AppBundle\Representation;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
use AppBundle\Entity\Ad;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*/
class SingleAd
{
/**
* @Type("AppBundle\Entity\Ad")
*/
public $data;
public function __construct(Ad $data)
{
$this->data = $data;
}
}
@@ -0,0 +1,27 @@
<?php
namespace AppBundle\Representation;
use AppBundle\Entity\Answer;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*/
class SingleAnswer
{
/**
* @Type("AppBundle\Entity\Answer")
*/
public $data;
public function __construct(Answer $data)
{
$this->data = $data;
}
}
@@ -0,0 +1,27 @@
<?php
namespace AppBundle\Representation;
use AppBundle\Entity\Company;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Type;
/**
* @Hateoas\Relation(
* "authenticated_user",
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
* )
*/
class SingleCompany
{
/**
* @Type("AppBundle\Entity\Company")
*/
public $data;
public function __construct(Company $data)
{
$this->data = $data;
}
}
@@ -0,0 +1,66 @@
<?php
namespace AppBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
// NOT USED AT THE MOMENT
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
{
public function createToken(Request $request, $providerKey)
{
$bearer = $request->headers->get('Authorization');
if (!$bearer) {
throw new BadCredentialsException();
}
return new PreAuthenticatedToken(
'anon.',
$bearer,
$providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$accessToken = $token->getCredentials();
$username = $userProvider->getUsernameForApiKey($accessToken);
if (!$username) {
// CAUTION: this message will be returned to the client
// (so don't put any un-trusted messages / error strings here)
throw new CustomUserMessageAuthenticationException(
sprintf('API Key "%s" does not exist.', $apiKey)
);
}
$user = $userProvider->loadUserByUsername($username);
return new PreAuthenticatedToken(
$user,
$accessToken,
$providerKey,
$user->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new Response("Authentication Failed :(", 401);
}
}
@@ -0,0 +1,47 @@
<?php
namespace AppBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
// NOT USED AT THE MOMENT
class ApiKeyUserProvider implements UserProviderInterface
{
public function getUsernameForApiKey($apiKey)
{
// Look up the username based on the token in the database, via
// an API call, or do something entirely different
// $username = ...;
return $username;
}
public function loadUserByUsername($username)
{
return new User(
$username,
null,
// the roles for the user - you may choose to determine
// these dynamically somehow based on the user
array('ROLE_API')
);
}
public function refreshUser(UserInterface $user)
{
// this is used for storing authentication in the session
// but in this example, the token is sent in each request,
// so authentication can be stateless. Throwing this exception
// is proper to make things stateless
throw new UnsupportedUserException();
}
public function supportsClass($class)
{
return User::class === $class;
}
}
@@ -126,17 +126,22 @@ class FOSUBUserProvider extends BaseFOSUBProvider
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$token = $this->container->get('security.token_storage')->getToken();
$serviceName = $response->getResourceOwner()->getName();
$data = $response->getData();
$userConnected = null;
if ($this->container->get('security.token_storage')->getToken()) {
$userConnected = $this->container->get('security.token_storage')->getToken()->getUser();
if ($token) {
$userConnected = $token->getUser();
}
//dump($userConnected);
$userEmail = $response->getEmail();
//dump($this->tokenData);
$user = $this->userManager->findUserByEmail($userEmail);
$userResponse = $this->resourceOwner->getUserInformation($this->tokenData);
//dump($userResponse);
if ($serviceName == "linkedin") {
//dump($userResponse->getUsername());
$id = $data['id'];
$birthday = null;
$gender = null;
@@ -227,4 +232,11 @@ class FOSUBUserProvider extends BaseFOSUBProvider
$user->$setter($response->getAccessToken());
return $user;
}
public function getUsernameForApiKey($apiKey)
{
$username = 'test';
return $username;
}
}
@@ -0,0 +1,207 @@
<?php
namespace AppBundle\Utils\Services;
use BenTools\WebPushBundle\Model\Message\Notification;
use Minishlink\WebPush\WebPush;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class NotificationSender implements ContainerAwareInterface
{
use ContainerAwareTrait;
protected $em;
protected $userManager;
protected $params;
protected $jsonNotificationFile;
public function __construct($em, $userManager, $params)
{
$this->em = $em;
$this->userManager = $userManager;
$this->params = $params;
$this->configure();
}
protected $options;
protected $auth;
protected $sender;
protected $subscriptionManager;
private function configure()
{
$config = $this->params['push_network_config'];
$this->options = array(
'TTL' => $config['ttl'], // defaults to 4 weeks
'urgency' => $config['urgency'], // protocol defaults to "normal"
'topic' => $config['topic'], // not defined by default,
//'batchSize' => 200, // defaults to 1000
);
$this->auth = array(
//'GCM' => 'AIzaSyB_TdmuATGFu2a3O-3Ikx7Yzk69ayJhZRc', // deprecated and optional, it's here only for compatibility reasons
'VAPID' => array(
'subject' => $config['service_mail_subject'],
'publicKey' => $config['public_key'], // got from https://web-push-codelab.appspot.com/
'privateKey' => $config['private_key'], // got from https://web-push-codelab.appspot.com/
),
);
$this->sender = new WebPush($this->auth, $this->options); //$this->container->get(WebPush::class);
$this->subscriptionManager = new UserSubscriptionManager($this->em);
}
///
/// ALL
///
public function sendPushToAllSubscribedUsers(string $filename, OutputInterface $output)
{
//get file .json
$str = file_get_contents($this->params["push_notification_file_path"] . $filename);
$this->jsonNotificationFile = json_decode($str, true);
$pushType = $this->jsonNotificationFile["parameters"]["pushType"];
// test push type
switch ($pushType) {
case 'general':
$users = $this->subscriptionManager->getAll();
break;
case 'users':
$users = $this->getSpecificUserSubscriptions($output);
break;
case 'profil':
$users = $this->getProfilCompletenessUserSubscriptions($output);
break;
case 'tags':
$users = $this->getTagMatchingUserSubscriptions($output);
break;
default:
$output->writeln('Error : pushType not known : ' . $pushType);
return;
}
//send
foreach ($users as $subscription) {
$this->sendNotification($output, $subscription);
}
$res = $this->sender->flush();
//purge db
if (is_array($res)) {
$this->PurgePushSubscriptions($res, $output);
}
}
///
/// SINGLE
///
public function sendSingleNotification(string $email, string $filename, OutputInterface $output)
{
$str = file_get_contents($this->params["push_notification_file_path"] . $filename);
$this->jsonNotificationFile = json_decode($str, true);
$user = $this->userManager->findUserBy(array('email' => $email));
$output->writeln('$user : ' . $user->getFirstname());
$users = $this->subscriptionManager->getAll();
foreach ($users as $subscription) {
$this->sendNotification($output, $subscription);
}
$res = $this->sender->flush();
if (is_array($res)) {
$this->PurgePushSubscriptions($res, $output);
}
}
private function getSpecificUserSubscriptions(OutputInterface $output)
{
$usersString = $this->jsonNotificationFile["parameters"]["users"];
$usersEmails = explode(";", $usersString);
return $this->subscriptionManager->findByEmails($usersEmails);
}
private function getProfilCompletenessUserSubscriptions(OutputInterface $output)
{
$completenessPercentage = (int) $this->jsonNotificationFile["parameters"]["profilCompletenessPercentage"];
return $this->subscriptionManager->findByProfilCompleteness($completenessPercentage);
}
private function getTagMatchingUserSubscriptions(OutputInterface $output)
{
$keywords = $this->jsonNotificationFile["parameters"]["keywords"];
$tags = explode(";", $keywords);
return $this->subscriptionManager->findByTagMatching($tags);
}
private function sendNotification(OutputInterface $output, $subscription)
{
!$output->isVerbose()?:$output->writeln('send to user ---> ' . $subscription->getEndpoint());
$this->sender->sendNotification(
$subscription->getEndpoint(),
new Notification($this->jsonNotificationFile["notification"]),
$subscription->getPublicKey(),
$subscription->getAuthToken()
);
}
public function sendTestNotification(string $email, string $filename, OutputInterface $output)
{
$user = $this->userManager->findUserBy(array('email' => $email));
!$output->isVerbose()?:$output->writeln('$user : ' . $user->getFirstname());
foreach ($this->subscriptionManager->findByUser($user) as $subscription) {
!$output->isVerbose()?:$output->writeln('send to user ---> ' . $subscription->getEndpoint());
$this->sendSampleNotification($output, $subscription);
}
$res = $this->sender->flush();
// $output->writeln('sendNotification flush result : ');
// var_dump($res);
if (is_array($res)) {
$this->PurgePushSubscriptions($res, $output);
}
}
private function sendSampleNotification(OutputInterface $output, $subscription)
{
$output->writeln('send sample to user ---> ' . $subscription->getEndpoint());
$this->sender->sendNotification(
$subscription->getEndpoint(),
$this->createTestNotification(),
$subscription->getPublicKey(),
$subscription->getAuthToken()
);
}
private function PurgePushSubscriptions($res, $output)
{
foreach ($res as $key => $value) {
if ($value['success'] == false) {
$hash = $this->subscriptionManager->hash($value['endpoint']);
$userSubscription = $this->subscriptionManager->findByHash($hash);
$this->subscriptionManager->delete($userSubscription[0]);
}
}
}
private function createTestNotification(): Notification
{
return new Notification([
'title' => 'Talents tube',
'body' => 'Nouvelle offre d\'emploi !',
'icon' => 'http://localhost/img/favicon.ico',
'image' => 'http://localhost/img/GROUPE-ROCHER-TT.jpg',
'data' => [
'message' => 'Ces entreprises recrutes en video',
'link' => 'http://localhost/app_dev.php/entreprise/liste/',
],
]);
}
}
@@ -0,0 +1,124 @@
<?php
namespace AppBundle\Utils\Services;
use AppBundle\Entity\UserSubscription;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface;
use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionManagerInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\User\UserInterface;
class UserSubscriptionManager implements UserSubscriptionManagerInterface
{
/**
* @var ManagerRegistry
*/
private $em;
/**
* UserSubscriptionManager constructor.
* @param ManagerRegistry $em
*/
public function __construct( $em)
{
$this->em = $em;
}
/**
* @inheritDoc
*/
public function factory(?UserInterface $user, string $subscriptionHash, array $subscription): UserSubscriptionInterface
{
return new UserSubscription($user, $subscriptionHash, $subscription);
}
/**
* @inheritDoc
*/
public function hash(string $endpoint): string {
return md5($endpoint);
}
/**
* @inheritDoc
*/
public function getUserSubscription(?UserInterface $user, string $subscriptionHash): ?UserSubscriptionInterface
{
$res = $this->em->getRepository(UserSubscription::class)->findOneBy([
'user' => $user,
'subscriptionHash' => $subscriptionHash,
]);
return $res;
}
/**
* @inheritDoc
*/
public function findByUser(UserInterface $user): iterable
{
return $this->em->getRepository(UserSubscription::class)->findBy([
'user' => $user,
]);
}
/**
* @inheritDoc
*/
public function findByEmails(array $emails): iterable
{
return $this->em->getRepository(UserSubscription::class)->findByEmails($emails);
}
/**
* @inheritDoc
*/
public function findByProfilCompleteness(int $completenessPercentage): iterable
{
return $this->em->getRepository(UserSubscription::class)->findByProfilCompleteness($completenessPercentage);
}
/**
* @inheritDoc
*/
public function findByTagMatching(array $tags): iterable
{
return $this->em->getRepository(UserSubscription::class)->findByTagMatching($tags);
}
/**
* @inheritDoc
*/
public function findByHash(string $subscriptionHash): iterable
{
return $this->em->getRepository(UserSubscription::class)->findBy([
'subscriptionHash' => $subscriptionHash,
]);
}
/**
* @inheritDoc
*/
public function getAll(): iterable
{
return $this->em->getRepository(UserSubscription::class)->findAll();
}
/**
* @inheritDoc
*/
public function save(UserSubscriptionInterface $userSubscription): void
{
$this->em->persist($userSubscription);
$this->em->flush();
}
/**
* @inheritDoc
*/
public function delete(UserSubscriptionInterface $userSubscription): void
{
$this->em->remove($userSubscription);
$this->em->flush();
}
}
@@ -9,8 +9,10 @@ trait AddressJsonTrait
/**
* @ORM\Column(name="address", type="json_document", nullable=true)
*
* @Groups({ "company_list", "company_detail", "answer_detail"})
*/
private $addresses;
public $addresses;
/***********************
* Non-mapped field
@@ -11,6 +11,8 @@ trait ExtraJsonTrait
* @var array
*
* @ORM\Column(name="extra", type="json_document", nullable=true)
*
* @Groups({"company_detail", "company_list"})
*/
private $extra;
@@ -8,6 +8,8 @@
namespace AppBundle\Utils\Traits;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\Groups;
trait StatusTrait
{
@@ -15,6 +17,9 @@ trait StatusTrait
* @var string
*
* @ORM\Column(name="status", type="string", length=255, nullable=true)
*
* @Accessor(getter="getStatus")
* @Groups({"answer_list", "answer_detail", "company_detail"})
*/
private $status;
@@ -11,8 +11,10 @@ trait TagsJsonTrait
* @var array
*
* @ORM\Column(name="public_tag", type="json_document", nullable=true)
*
* @Groups({"company_detail"})
*/
private $publicTag;
public $publicTag;
/***********************
* Non-mapped field
@@ -3,6 +3,7 @@
namespace AppBundle\Utils\Traits;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
trait TimestampableTrait
{
@@ -10,6 +11,7 @@ trait TimestampableTrait
* @var \DateTime $cTime
*
* @ORM\Column(name="c_time", type="datetime", nullable=true)
* @Groups({"answer_list", "answer_detail"})
*/
private $cTime;
+5
View File
@@ -0,0 +1,5 @@
XSym
0017
8431887d5273f9711cebfb2f972879df
/usr/bin/uglifyjs
@@ -389,7 +389,7 @@ class SymfonyRequirements extends RequirementCollection
{
/* mandatory requirements follow */
$installedPhpVersion = phpversion();
$installedPhpVersion = PHP_VERSION;
$requiredPhpVersion = $this->getPhpRequiredVersion();
$this->addRecommendation(
@@ -448,15 +448,8 @@ class SymfonyRequirements extends RequirementCollection
}
if (false !== $requiredPhpVersion && version_compare($installedPhpVersion, $requiredPhpVersion, '>=')) {
$timezones = array();
foreach (DateTimeZone::listAbbreviations() as $abbreviations) {
foreach ($abbreviations as $abbreviation) {
$timezones[$abbreviation['timezone_id']] = true;
}
}
$this->addRequirement(
isset($timezones[@date_default_timezone_get()]),
in_array(@date_default_timezone_get(), DateTimeZone::listIdentifiers(), true),
sprintf('Configured default timezone "%s" must be supported by your installation of PHP', @date_default_timezone_get()),
'Your default timezone is not supported by PHP. Check for typos in your <strong>php.ini</strong> file and have a look at the list of deprecated timezones at <a href="http://php.net/manual/en/timezones.others.php">http://php.net/manual/en/timezones.others.php</a>.'
);
@@ -731,7 +724,7 @@ class SymfonyRequirements extends RequirementCollection
'Install and/or enable a <strong>PHP accelerator</strong> (highly recommended).'
);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
if ('WIN' === strtoupper(substr(PHP_OS, 0, 3))) {
$this->addRecommendation(
$this->getRealpathCacheSize() >= 5 * 1024 * 1024,
'realpath_cache_size should be at least 5M in php.ini',
+11
View File
@@ -0,0 +1,11 @@
Copyright (c) 2011-2013, Benjamin Eberlei
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
@@ -0,0 +1,54 @@
{
"name": "beberlei/assert",
"description": "Thin assertion library for input validation in business models.",
"authors": [
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de",
"role": "Lead Developer"
},
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com",
"role": "Collaborator"
}
],
"license": "BSD-2-Clause",
"keywords": [
"assert",
"assertion",
"validation"
],
"config": {
"sort-packages": true
},
"require": {
"php": ">=5.3",
"ext-mbstring": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.1.1",
"phpunit/phpunit": "^4.8.35|^5.7"
},
"autoload": {
"psr-4": {
"Assert\\": "lib/Assert"
},
"files": [
"lib/Assert/functions.php"
]
},
"autoload-dev": {
"psr-4": {
"Assert\\Tests\\": "tests/Assert/Tests"
},
"files": [
"tests/Assert/Tests/Fixtures/functions.php"
]
},
"scripts": {
"assert:generate-docs": "php bin/generate_method_docs.php",
"assert:cs-lint": "php-cs-fixer fix --diff -vvv --dry-run",
"assert:cs-fix": "php-cs-fixer fix . -vvv || true"
}
}
@@ -0,0 +1,99 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
/**
* AssertionChain factory.
*/
abstract class Assert
{
/** @var string */
protected static $lazyAssertionExceptionClass = 'Assert\LazyAssertionException';
/** @var string */
protected static $assertionClass = 'Assert\Assertion';
/**
* Start validation on a value, returns {@link AssertionChain}.
*
* The invocation of this method starts an assertion chain
* that is happening on the passed value.
*
* @example
*
* Assert::that($value)->notEmpty()->integer();
* Assert::that($value)->nullOr()->string()->startsWith("Foo");
*
* The assertion chain can be stateful, that means be careful when you reuse
* it. You should never pass around the chain.
*
* @param mixed $value
* @param string $defaultMessage
* @param string $defaultPropertyPath
*
* @return \Assert\AssertionChain
*/
public static function that($value, $defaultMessage = null, $defaultPropertyPath = null)
{
$assertionChain = new AssertionChain($value, $defaultMessage, $defaultPropertyPath);
return $assertionChain
->setAssertionClassName(static::$assertionClass)
;
}
/**
* Start validation on a set of values, returns {@link AssertionChain}.
*
* @param mixed $values
* @param string $defaultMessage
* @param string $defaultPropertyPath
*
* @return \Assert\AssertionChain
*/
public static function thatAll($values, $defaultMessage = null, $defaultPropertyPath = null)
{
return static::that($values, $defaultMessage, $defaultPropertyPath)->all();
}
/**
* Start validation and allow NULL, returns {@link AssertionChain}.
*
* @param mixed $value
* @param string $defaultMessage
* @param string $defaultPropertyPath
*
* @return \Assert\AssertionChain
*/
public static function thatNullOr($value, $defaultMessage = null, $defaultPropertyPath = null)
{
return static::that($value, $defaultMessage, $defaultPropertyPath)->nullOr();
}
/**
* Create a lazy assertion object.
*
* @return \Assert\LazyAssertion
*/
public static function lazy()
{
$lazyAssertion = new LazyAssertion();
return $lazyAssertion
->setAssertClass(\get_called_class())
->setExceptionClass(static::$lazyAssertionExceptionClass)
;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,230 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
use LogicException;
use ReflectionClass;
/**
* Chaining builder for assertions.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*
* @method AssertionChain alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric.
* @method AssertionChain base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
* @method AssertionChain between(mixed $lowerLimit, mixed $upperLimit, string $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit.
* @method AssertionChain betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit.
* @method AssertionChain betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min,max lengths.
* @method AssertionChain boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean.
* @method AssertionChain choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices.
* @method AssertionChain choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content.
* @method AssertionChain classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists.
* @method AssertionChain contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars.
* @method AssertionChain count(int $count, string $message = null, string $propertyPath = null) Assert that the count of countable is equal to count.
* @method AssertionChain date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format.
* @method AssertionChain defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
* @method AssertionChain digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit.
* @method AssertionChain directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists.
* @method AssertionChain e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number.
* @method AssertionChain email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL).
* @method AssertionChain endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars.
* @method AssertionChain eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using == ).
* @method AssertionChain extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded.
* @method AssertionChain extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed.
* @method AssertionChain false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False.
* @method AssertionChain file(string|callable $message = null, string $propertyPath = null) Assert that a file exists.
* @method AssertionChain float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float.
* @method AssertionChain greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit.
* @method AssertionChain greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit.
* @method AssertionChain implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface.
* @method AssertionChain inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice().
* @method AssertionChain integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer.
* @method AssertionChain integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish.
* @method AssertionChain interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists.
* @method AssertionChain ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address.
* @method AssertionChain ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address.
* @method AssertionChain ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address.
* @method AssertionChain isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array.
* @method AssertionChain isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object.
* @method AssertionChain isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable.
* @method AssertionChain isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name.
* @method AssertionChain isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string.
* @method AssertionChain isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object.
* @method AssertionChain isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource.
* @method AssertionChain isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object.
* @method AssertionChain keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array.
* @method AssertionChain keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset().
* @method AssertionChain keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array.
* @method AssertionChain length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length.
* @method AssertionChain lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit.
* @method AssertionChain lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit.
* @method AssertionChain max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit.
* @method AssertionChain maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars.
* @method AssertionChain methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object.
* @method AssertionChain min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit.
* @method AssertionChain minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long.
* @method AssertionChain noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty.
* @method AssertionChain notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank.
* @method AssertionChain notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty.
* @method AssertionChain notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty.
* @method AssertionChain notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using == ).
* @method AssertionChain notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices.
* @method AssertionChain notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name.
* @method AssertionChain notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null.
* @method AssertionChain notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using === ).
* @method AssertionChain null(string|callable $message = null, string $propertyPath = null) Assert that value is null.
* @method AssertionChain numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric.
* @method AssertionChain objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists.
* @method AssertionChain phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version.
* @method AssertionChain propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist.
* @method AssertionChain propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists.
* @method AssertionChain range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers.
* @method AssertionChain readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable.
* @method AssertionChain regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex.
* @method AssertionChain same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===).
* @method AssertionChain satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback.
* @method AssertionChain scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar.
* @method AssertionChain startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars.
* @method AssertionChain string(string|callable $message = null, string $propertyPath = null) Assert that value is a string.
* @method AssertionChain subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name.
* @method AssertionChain true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True.
* @method AssertionChain url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL.
* @method AssertionChain uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID.
* @method AssertionChain version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions.
* @method AssertionChain writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable.
*/
class AssertionChain
{
private $value;
private $defaultMessage;
private $defaultPropertyPath;
/**
* Return each assertion as always valid.
*
* @var bool
*/
private $alwaysValid = false;
/**
* Perform assertion on every element of array or traversable.
*
* @var bool
*/
private $all = false;
/** @var string|Assertion Class to use for assertion calls */
private $assertionClassName = 'Assert\Assertion';
public function __construct($value, $defaultMessage = null, $defaultPropertyPath = null)
{
$this->value = $value;
$this->defaultMessage = $defaultMessage;
$this->defaultPropertyPath = $defaultPropertyPath;
}
/**
* Call assertion on the current value in the chain.
*
* @param string $methodName
* @param array $args
*
* @return \Assert\AssertionChain
*/
public function __call($methodName, $args)
{
if (true === $this->alwaysValid) {
return $this;
}
if (!\method_exists($this->assertionClassName, $methodName)) {
throw new \RuntimeException("Assertion '" . $methodName . "' does not exist.");
}
$reflClass = new ReflectionClass($this->assertionClassName);
$method = $reflClass->getMethod($methodName);
\array_unshift($args, $this->value);
$params = $method->getParameters();
foreach ($params as $idx => $param) {
if (isset($args[$idx])) {
continue;
}
if ('message' == $param->getName()) {
$args[$idx] = $this->defaultMessage;
}
if ('propertyPath' == $param->getName()) {
$args[$idx] = $this->defaultPropertyPath;
}
}
if ($this->all) {
$methodName = 'all' . $methodName;
}
\call_user_func_array(array($this->assertionClassName, $methodName), $args);
return $this;
}
/**
* Switch chain into validation mode for an array of values.
*
* @return \Assert\AssertionChain
*/
public function all()
{
$this->all = true;
return $this;
}
/**
* Switch chain into mode allowing nulls, ignoring further assertions.
*
* @return \Assert\AssertionChain
*/
public function nullOr()
{
if (null === $this->value) {
$this->alwaysValid = true;
}
return $this;
}
/**
* @param string $className
*
* @return $this
*/
public function setAssertionClassName($className)
{
if (!\is_string($className)) {
throw new LogicException('Exception class name must be passed as a string');
}
if ('Assert\Assertion' !== $className && !\is_subclass_of($className, 'Assert\Assertion')) {
throw new LogicException($className . ' is not (a subclass of) Assert\Assertion');
}
$this->assertionClassName = $className;
return $this;
}
}
@@ -0,0 +1,24 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
interface AssertionFailedException
{
public function getPropertyPath();
public function getValue();
public function getConstraints();
}
@@ -0,0 +1,65 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
class InvalidArgumentException extends \InvalidArgumentException implements AssertionFailedException
{
private $propertyPath;
private $value;
private $constraints;
public function __construct($message, $code, $propertyPath, $value, array $constraints = array())
{
parent::__construct($message, $code);
$this->propertyPath = $propertyPath;
$this->value = $value;
$this->constraints = $constraints;
}
/**
* User controlled way to define a sub-property causing
* the failure of a currently asserted objects.
*
* Useful to transport information about the nature of the error
* back to higher layers.
*
* @return string
*/
public function getPropertyPath()
{
return $this->propertyPath;
}
/**
* Get the value that caused the assertion to fail.
*
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* Get the constraints that applied to the failed assertion.
*
* @return array
*/
public function getConstraints()
{
return $this->constraints;
}
}
@@ -0,0 +1,216 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
use LogicException;
/**
* Chaining builder for lazy assertions.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
*
* @method LazyAssertion alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric.
* @method LazyAssertion base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
* @method LazyAssertion between(mixed $lowerLimit, mixed $upperLimit, string $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit.
* @method LazyAssertion betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit.
* @method LazyAssertion betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min,max lengths.
* @method LazyAssertion boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean.
* @method LazyAssertion choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices.
* @method LazyAssertion choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content.
* @method LazyAssertion classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists.
* @method LazyAssertion contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars.
* @method LazyAssertion count(int $count, string $message = null, string $propertyPath = null) Assert that the count of countable is equal to count.
* @method LazyAssertion date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format.
* @method LazyAssertion defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
* @method LazyAssertion digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit.
* @method LazyAssertion directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists.
* @method LazyAssertion e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number.
* @method LazyAssertion email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL).
* @method LazyAssertion endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars.
* @method LazyAssertion eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using == ).
* @method LazyAssertion extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded.
* @method LazyAssertion extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed.
* @method LazyAssertion false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False.
* @method LazyAssertion file(string|callable $message = null, string $propertyPath = null) Assert that a file exists.
* @method LazyAssertion float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float.
* @method LazyAssertion greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit.
* @method LazyAssertion greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit.
* @method LazyAssertion implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface.
* @method LazyAssertion inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice().
* @method LazyAssertion integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer.
* @method LazyAssertion integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish.
* @method LazyAssertion interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists.
* @method LazyAssertion ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address.
* @method LazyAssertion ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address.
* @method LazyAssertion ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address.
* @method LazyAssertion isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array.
* @method LazyAssertion isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object.
* @method LazyAssertion isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable.
* @method LazyAssertion isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name.
* @method LazyAssertion isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string.
* @method LazyAssertion isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object.
* @method LazyAssertion isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource.
* @method LazyAssertion isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object.
* @method LazyAssertion keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array.
* @method LazyAssertion keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset().
* @method LazyAssertion keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array.
* @method LazyAssertion length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length.
* @method LazyAssertion lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit.
* @method LazyAssertion lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit.
* @method LazyAssertion max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit.
* @method LazyAssertion maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars.
* @method LazyAssertion methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object.
* @method LazyAssertion min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit.
* @method LazyAssertion minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long.
* @method LazyAssertion noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty.
* @method LazyAssertion notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank.
* @method LazyAssertion notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty.
* @method LazyAssertion notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty.
* @method LazyAssertion notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using == ).
* @method LazyAssertion notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices.
* @method LazyAssertion notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name.
* @method LazyAssertion notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null.
* @method LazyAssertion notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using === ).
* @method LazyAssertion null(string|callable $message = null, string $propertyPath = null) Assert that value is null.
* @method LazyAssertion numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric.
* @method LazyAssertion objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists.
* @method LazyAssertion phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version.
* @method LazyAssertion propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist.
* @method LazyAssertion propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists.
* @method LazyAssertion range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers.
* @method LazyAssertion readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable.
* @method LazyAssertion regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex.
* @method LazyAssertion same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===).
* @method LazyAssertion satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback.
* @method LazyAssertion scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar.
* @method LazyAssertion startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars.
* @method LazyAssertion string(string|callable $message = null, string $propertyPath = null) Assert that value is a string.
* @method LazyAssertion subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name.
* @method LazyAssertion true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True.
* @method LazyAssertion url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL.
* @method LazyAssertion uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID.
* @method LazyAssertion version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions.
* @method LazyAssertion writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable.
* @method LazyAssertion all() Switch chain into validation mode for an array of values.
* @method LazyAssertion nullOr() Switch chain into mode allowing nulls, ignoring further assertions.
*/
class LazyAssertion
{
private $currentChainFailed = false;
private $alwaysTryAll = false;
private $thisChainTryAll = false;
private $currentChain;
private $errors = array();
/** @var string The class to use as AssertionChain factory */
private $assertClass = 'Assert\Assert';
/** @var string|LazyAssertionException The class to use for exceptions */
private $exceptionClass = 'Assert\LazyAssertionException';
public function that($value, $propertyPath, $defaultMessage = null)
{
$this->currentChainFailed = false;
$this->thisChainTryAll = false;
$assertClass = $this->assertClass;
$this->currentChain = $assertClass::that($value, $defaultMessage, $propertyPath);
return $this;
}
public function tryAll()
{
if (!$this->currentChain) {
$this->alwaysTryAll = true;
}
$this->thisChainTryAll = true;
return $this;
}
public function __call($method, $args)
{
if (false === $this->alwaysTryAll
&& false === $this->thisChainTryAll
&& true === $this->currentChainFailed
) {
return $this;
}
try {
\call_user_func_array(array($this->currentChain, $method), $args);
} catch (AssertionFailedException $e) {
$this->errors[] = $e;
$this->currentChainFailed = true;
}
return $this;
}
/**
* @throws \Assert\LazyAssertionException
*
* @return bool
*/
public function verifyNow()
{
if ($this->errors) {
throw \call_user_func(array($this->exceptionClass, 'fromErrors'), $this->errors);
}
return true;
}
/**
* @param string $className
*
* @return $this
*/
public function setAssertClass($className)
{
if (!\is_string($className)) {
throw new LogicException('Assert class name must be passed as a string');
}
if ('Assert\Assert' !== $className && !\is_subclass_of($className, 'Assert\Assert')) {
throw new LogicException($className . ' is not (a subclass of) Assert\Assert');
}
$this->assertClass = $className;
return $this;
}
/**
* @param string $className
*
* @return $this
*/
public function setExceptionClass($className)
{
if (!\is_string($className)) {
throw new LogicException('Exception class name must be passed as a string');
}
if ('Assert\LazyAssertionException' !== $className && !\is_subclass_of($className, 'Assert\LazyAssertionException')) {
throw new LogicException($className . ' is not (a subclass of) Assert\LazyAssertionException');
}
$this->exceptionClass = $className;
return $this;
}
}
@@ -0,0 +1,52 @@
<?php
/**
* Assert
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace Assert;
class LazyAssertionException extends InvalidArgumentException
{
/**
* @var InvalidArgumentException[]
*/
private $errors = array();
/**
* @param InvalidArgumentException[] $errors
*
* @return self
*/
public static function fromErrors(array $errors)
{
$message = \sprintf('The following %d assertions failed:', \count($errors)) . "\n";
$i = 1;
foreach ($errors as $error) {
$message .= \sprintf("%d) %s: %s\n", $i++, $error->getPropertyPath(), $error->getMessage());
}
return new static($message, $errors);
}
public function __construct($message, array $errors)
{
parent::__construct($message, 0, null, null);
$this->errors = $errors;
}
public function getErrorExceptions()
{
return $this->errors;
}
}

Some files were not shown because too many files have changed in this diff Show More