Compare commits

...

66 Commits

Author SHA1 Message Date
Maxime Thévenot 703ec9a1bb Fix : bug on talent deleting 2018-04-26 17:18:42 +02:00
Maxime Thévenot 4a72e4dfe6 Merge branch 'develop' of https://git.e-declic.net/talents-tube/website into develop
# Conflicts:
#	volume/www/website/www/src/AppBundle/Entity/Company.php
2018-04-26 16:42:01 +02:00
Maxime Thévenot 607f7706ca Feat : add capability to delete company from secret admin 2018-04-26 16:40:49 +02:00
Thomas MONCHICOURT b0b1179bdc Feat : Modification listing company #6269 @1h30 2018-04-24 14:16:19 +02:00
Thomas MONCHICOURT 0e2494797e Fix : Bloc vidéo après mot clés #6266 @0h25 2018-04-23 16:09:00 +02:00
Thomas MONCHICOURT 69a7595966 Fix : page detail territoire 2018-04-23 16:04:33 +02:00
Thomas MONCHICOURT e404b4d876 Merge branch 'develop' 2018-04-23 16:00:15 +02:00
Thomas MONCHICOURT fa8b21b93c Merge branch 'develop' of https://git.e-declic.net/talents-tube/website into develop 2018-04-23 15:59:43 +02:00
Thomas MONCHICOURT 8e8312c0f9 Feat : modification video territoire #6266 @0H15 2018-04-23 15:59:40 +02:00
Maxime Thévenot 0297191e07 Fix : update teritory sorting order 2018-04-20 15:23:45 +02:00
Maxime Thévenot e64ce55b66 Merge branch 'develop' 2018-04-20 15:16:04 +02:00
Thomas MONCHICOURT eda0562edc Feat : mise en ligne vidéo albéa + changement home 2018-04-20 15:11:53 +02:00
Maxime Thévenot 01f5823885 Feat : permit admin to refresh vimeo image + sorting list 2018-04-20 15:10:44 +02:00
Thomas MONCHICOURT 9ed2745e8d Feat : mise en ligne vidéo albéa + changement home 2018-04-17 09:33:37 +02:00
Thomas MONCHICOURT 82c4911770 Feat : Modification du code et mise en git #6185 @0h10 2018-04-16 09:34:10 +02:00
Thomas MONCHICOURT 8df9b7af43 Feat : Ajout champ description admin pour territoire #6181 @1h 2018-04-13 10:50:33 +02:00
Thomas MONCHICOURT 71259c40c6 Feat : Ajout d’un col list user + action resend confirm mail #6151 @0h20 2018-04-09 14:49:14 +02:00
Thomas MONCHICOURT 2dd559fa64 Feat : intervention albéa @0h15 2018-03-30 17:04:26 +02:00
Thomas MONCHICOURT 90ae12995f Fix : admin set presentation on null 2018-03-27 15:16:11 +02:00
Thomas MONCHICOURT 7aa4a92cb6 Feat : Ajout listing user en admin #6108 @2h 2018-03-27 14:29:52 +02:00
Thomas MONCHICOURT 6a9b48d629 Fix : modification linkedin 2018-03-15 14:27:13 +01:00
Thomas MONCHICOURT 032d10bb50 Fix: connexion FB 2018-03-15 12:34:07 +01:00
Thomas MONCHICOURT 7731dd2c23 Fix : erreur js vimeo 2018-03-06 09:56:05 +01:00
Thomas MONCHICOURT 8c6e8f14a4 Fix: erreur photo profil talent @0h15 2018-03-05 11:31:45 +01:00
Thomas MONCHICOURT f1c795e8cd Fix : js date picker 2018-02-15 11:30:11 +01:00
Thomas MONCHICOURT 5dd437d939 Feat : increase lifetime sessions 2018-02-15 10:46:05 +01:00
Thomas MONCHICOURT 59f6854379 Fix : popup option connect FB 2018-02-15 10:24:01 +01:00
Thomas MONCHICOURT c2450d3929 Fix : modification app facebook 2018-02-15 10:14:47 +01:00
Thomas MONCHICOURT 2f626dbad5 Fix : robots txt 2018-02-13 15:20:32 +01:00
Thomas MONCHICOURT 8bccabbcf6 Fix : suppression dissalow 2018-02-13 15:04:53 +01:00
Maxime Thévenot 766335bb19 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2018-02-13 14:32:58 +01:00
Maxime Thévenot 708e1f1c87 Conf : Update .gitignore 2018-02-13 14:32:53 +01:00
Thomas MONCHICOURT 1d0e0e4c48 Merge branch 'master' into develop 2018-02-09 15:34:05 +01:00
Thomas MONCHICOURT a790f99adb Fix : re error 404 2018-02-09 15:32:59 +01:00
Thomas MONCHICOURT e98a2488eb Fix : error 404 error #5890 @1h30 2018-02-09 15:32:43 +01:00
Maxime Thévenot 8b7a79ef8d Conf : Update robot.txt 2018-02-08 17:12:11 +01:00
Thomas MONCHICOURT 645cf1f05a Fix : change password 2018-02-08 17:12:00 +01:00
Thomas MONCHICOURT 974629794d Merge branch 'develop' 2018-02-07 09:17:43 +01:00
Thomas MONCHICOURT f23e906168 Feat: suppression voeux 2018 2018-02-07 09:17:19 +01:00
Thomas MONCHICOURT 5a47ac168e Fix : liste témoignages 2018-02-02 15:06:14 +01:00
Thomas MONCHICOURT a35647ca1d Merge branch 'develop' 2018-02-02 14:52:38 +01:00
Thomas MONCHICOURT 231a692369 Feat : Ajout des temoignage dans d’autre page #5662 @0h20 2018-02-02 14:52:28 +01:00
Thomas MONCHICOURT 1ad2d8bf1a Merge branch 'develop' 2018-02-02 14:28:47 +01:00
Thomas MONCHICOURT 2047322161 Feat : youtube #5845 @0h15 2018-02-02 14:28:29 +01:00
Thomas MONCHICOURT f90c907942 Feat : add a hover stop on carousel 2018-02-02 14:17:33 +01:00
Thomas MONCHICOURT a2d0a9539f Feat : modif temoignages #5662 @0h20 2018-02-02 12:02:49 +01:00
Thomas MONCHICOURT d5f448483c Feat : Modification #5662 @0h30 2018-01-25 15:15:54 +01:00
Thomas MONCHICOURT 8f12cddd86 Feat : template temoignages #5662 @1h15 2018-01-25 12:12:19 +01:00
Thomas MONCHICOURT 0f195907c5 Merge branch 'develop' 2018-01-24 12:04:38 +01:00
Thomas MONCHICOURT 8dabe7ba82 Fix : provider security 2018-01-24 12:04:20 +01:00
Thomas MONCHICOURT 0bfed4b932 Fix : probleme css dot nav tuto 2018-01-22 15:36:16 +01:00
Thomas MONCHICOURT bf875db942 Fix : dropzone js error 2018-01-22 15:09:57 +01:00
Thomas MONCHICOURT 5c47a00d0e Fix : Start to first panel tuto when restart 2018-01-22 15:09:49 +01:00
Thomas MONCHICOURT 0f8fe7732e Fix : amelioration graphique tuto 2018-01-22 15:09:36 +01:00
Thomas MONCHICOURT bed4cbc7b1 Fix : Start to first panel tuto when restart 2018-01-22 14:27:48 +01:00
Thomas MONCHICOURT b09ca38415 Fix : dropzone js error 2018-01-22 14:07:12 +01:00
Thomas MONCHICOURT c0f09f715c Fix : delevery address 2018-01-22 12:10:57 +01:00
Thomas MONCHICOURT 77d695f67a Fix : conf preprod 2018-01-22 09:30:44 +01:00
Thomas MONCHICOURT 4cb07a74b6 Fix : conf preprod 2018-01-22 09:29:58 +01:00
Thomas MONCHICOURT 43997a3493 Feat : Merge develop => master à la mano 2018-01-19 15:53:06 +01:00
Thomas MONCHICOURT e6316504f1 Feat : Voeux 2018 #5816 @2h 2018-01-18 11:21:05 +01:00
Thomas MONCHICOURT d8ac0993d6 Fix : port docker dev 2018-01-17 14:59:17 +01:00
Thomas MONCHICOURT 67575e53e4 Fix : stats 2018-01-15 11:27:29 +01:00
Thomas MONCHICOURT 182a1b5078 Fix : nginx conf prod 2018-01-11 11:00:33 +01:00
Thomas MONCHICOURT 4b9cd98266 Fix : correction 2018-01-11 10:50:58 +01:00
Thomas MONCHICOURT cf4e5020f5 Fix : conf static 2017-12-27 11:40:41 +01:00
3399 changed files with 123877 additions and 15943 deletions
+2 -1
View File
@@ -6,4 +6,5 @@
!/volume/www
/volume/www/**/conf/nginx.conf
/backup
/conf/env/*.env
/conf/env/*.env
volume/www/website/.idea
+1 -1
View File
@@ -4,7 +4,7 @@ services:
nginx:
ports:
- "8080:80"
- "80:80"
volumes:
- ../volume/www:/home/www:cached
restart: "no"
+1 -1
View File
@@ -16,7 +16,7 @@ server {
# DEV
location / {
try_files $uri /app_dev.php$is_args$args;
try_files $uri /app.php$is_args$args;
}
location ~ ^/(app_dev|config)\.php(/|$) {
+3 -1
View File
@@ -36,7 +36,7 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /app.php$is_args$args;
@@ -58,6 +58,7 @@ server {
# for more information).
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param HTTPS on;
}
# PROD
@@ -78,6 +79,7 @@ server {
# http://domain.tld/app.php/some-path
# Remove the internal directive to allow URIs like this
internal;
fastcgi_param HTTPS on;
}
# ---- PRESTASHOP ----
+16 -1
View File
@@ -6,6 +6,21 @@ upstream store_php {
server tt-website.store-php.prod:9000;
}
server {
listen 80;
server_name static.talentstube.com;
index index.html;
root /home/www/website/www/web/uploads/;
access_log /home/www/website/log/access.log vhosts;
error_log /home/www/website/log/error.log;
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
@@ -13,7 +28,7 @@ server {
client_max_body_size 500M;
root /home/www/www.talentstube.com/www/web;
root /home/www/website/www/web;
access_log /home/www/website/log/access.log vhosts;
error_log /home/www/website/log/error.log;
+4
View File
@@ -44,6 +44,10 @@ class AppKernel extends Kernel
new Edeclic\PrestashopBridgeBundle\EdeclicPrestashopBridgeBundle(),
new Edeclic\HistoryBundle\EdeclicHistoryBundle(),
new AppBundle\AppBundle(),
//oAuth
new Http\HttplugBundle\HttplugBundle(),
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
@@ -38,20 +38,20 @@
{{ form_row(form.plainPassword.second, {'label': 'Répéter le mot de passe'}) }}
</div>
</div>
{% if destination_login is defined %}
<input type="hidden" name="_target_path" value="{{ destination_login }}" />
{% endif %}
<div class="row">
<div class="input-field col s12">
{% set label = 'user.cgu.label'|trans({'%link_start%' : '<a href="'~path('service_cgu')~'">', '%link_end%' : '</a>'}, 'messages') | raw %}
{{ form_errors(form.cgu) }}
{{ form_widget(form.cgu) }}
{{ form_label(form.cgu) }}
<br />
{#{{ form_widget(form.cgu) }}
{{ form_label(form.cgu) }}#}
</div>
</div>
<div class="row">
<div class="input-field col s12">
<a href="{{ path('service_cgu') }}" title="conditions d'utilisations" style="margin-left:45px;">Lire les conditions générales d'utilisations</a>
Lire les conditions générales d'utilisations</a>
<br /><br />
</div>
</div>
@@ -1,16 +1,78 @@
{% block fos_user_content %}
<div class="row">
<div class="col s12 m12 l6 col-login-first col-login">
<h4>Connexion</h4>
<div class="row login_face active_face">
<div class="col s12 col-login-first col-login">
<h4 class="color-blue1 pull-left">Connexion</h4>
<div class="pull-right">
ou
<a href="#" class="color-blue1 change_to_register">
Créer un compte
</a>
</div>
<br class="clearfix"/>
{{ include('@FOSUser/Security/login_content.html.twig') }}
</div>
<div class="col s12 m12 l6 col-login-first col-login-subscribe hide-on-med-and-down">
<div class="center-align">
<strong>Je ne possède pas de<br />compte Talents Tube</strong>
</div>
<div class="row register_face">
<div class="col s12 col-login-first col-login">
<h4 class="color-blue1 pull-left">Créer un compte</h4>
<div class="pull-right">
ou
<a href="#" class="color-blue1 change_to_login">
Se connecter
</a>
</div>
<a href="{{ path('fos_user_registration_register') }}" class="btn btn-default btn-round">
Créer un compte
</a>
<br class="clearfix"/>
{{ form_start(register_form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }}
{{ form_errors(register_form) }}
<div class="row">
<div class="input-field col s6">
{{ form_row(register_form.firstname, {'label': 'Prénom'}) }}
</div>
<div class="input-field col s6">
{{ form_row(register_form.lastname, {'label': 'Nom'}) }}
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form_row(register_form.email, {'label': 'E-mail'}) }}
</div>
</div>
<div class="hide">
{{ form_row(register_form.username, {'label': 'Username'}) }}
</div>
<div class="row">
<div class="input-field col s12">
{{ form_row(register_form.plainPassword.first, {'label': 'Mot de passe'}) }}
</div>
</div>
<div class="row">
<div class="input-field col s12">
{{ form_row(register_form.plainPassword.second, {'label': 'Répéter le mot de passe'}) }}
</div>
</div>
{% if destination_login is defined %}
<input type="hidden" name="_target_path" value="{{ destination_login }}" />
{% endif %}
<div class="row">
<div class="input-field col s12">
{% set label = 'user.cgu.label'|trans({'%link_start%' : '<a style="margin-bottom:25px;" target="_blank" href="'~path('service_cgu')~'">', '%link_end%' : '</a>'}, 'messages') | raw %}
{{ form_errors(register_form.cgu) }}
{{ form_widget(register_form.cgu) }}
{% block form_label %}
{% spaceless %}
<label for="fos_user_registration_form_cgu">
Je déclare avoir pris connaissance et accepté les termes et les <a target="_blank" href="{{ path("service_cgu") }}">conditions générales dutilisation</a>
</label>
{% endspaceless %}
{% endblock %}
</div>
</div>
<div class="row m-t-30">
<div class="col s12 center-align">
<input class="btn btn-default btn-round" type="submit" id="_submit_register" name="_submit_register" value="Créer un compte" />
</div>
</div>
{{ form_end(register_form) }}
</div>
</div>
{% endblock fos_user_content %}
@@ -1,5 +1,6 @@
{% trans_default_domain 'FOSUserBundle' %}
{% include 'default/facebook.html.twig' %}
{% if error %}
<div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
@@ -7,38 +8,33 @@
{% if csrf_token %}
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
{% endif %}
<div class="row">
<div class="row field-login">
<div class="input-field col s12">
<label for="username">{{ 'security.login.username'|trans }}</label>
<label for="username">e-mail</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" required="required" />
</div>
</div>
<div class="row">
<div class="row field-login">
<div class="input-field col s12">
<label for="password">{{ 'security.login.password'|trans }}</label>
<input type="password" id="password" name="_password" required="required" />
</div>
</div>
<p>
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
<label for="remember_me">{{ 'security.login.remember_me'|trans }}</label>
</p>
<br />
<div class="row hide-on-large-only">
<div class="col s6">
<input class="btn btn-default btn-round" type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans }}" /><br />
<a href="{{path('fos_user_resetting_request')}}"><span class="tiny-text font-black m-l-10">J'ai oublié mon mot de passe</span></a>
</div>
<div class="col s6">
<a href="{{ path('fos_user_registration_register') }}" class="btn btn-default btn-round">
Créer un compte
</a>
</div>
</div>
<div class="row hide-on-med-and-down">
<div class="row field-login-checkbox">
<div class="col s12">
<input class="btn btn-default btn-round" type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans }}" /><br />
<a href="{{path('fos_user_resetting_request')}}"><span class="tiny-text font-black m-l-10">J'ai oublié mon mot de passe</span></a>
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
<label for="remember_me">{{ 'security.login.remember_me'|trans }}</label>
<br class="clearfix"/>
</div>
</div>
</form>
<br />
{% if destination_login is defined %}
<input type="hidden" name="_target_path" value="{{ destination_login }}" />
{% endif %}
<div class="row">
<div class="col s12 center-align">
<input class="btn btn-default btn-round" type="submit" id="_submit" name="_submit" value="Se connecter" /><br />
<a href="{{path('fos_user_resetting_request')}}"><span class="tiny-text font-black m-l-10">Mot de passe oublié ?</span></a>
</div>
</div>
</form>
@@ -1,17 +1,12 @@
{% extends 'base.html.twig' %}
{% block urlCanonical %}
#!
{% endblock %}
{% block content %}
<div class="row">
<div class="col s12">
<h2 class="center-align">Page introuvable</h2>
<p class="center-align">
Cette page n'existe plus.<br/><br/>
<a class="btn btn-default" href="{{ path('homepage') }}">Retour à l'accueil</a>
</p>
</div>
{% block content %}
<div class="row">
<div class="col s12">
<h2 class="center-align m-t-100">Page introuvable</h2>
<p class="center-align">
Cette page n'existe plus.<br/><br/>
<a class="btn btn-default" href="{{ path('homepage') }}">Retour à l'accueil</a>
</p>
</div>
{% endblock %}
</div>
{% endblock %}
@@ -66,6 +66,10 @@
title="Modifier">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
</a>
<a href="{{ path('admin_ad_refresh_img',{'id':ad.id}) }}" data-toggle="tooltip"
title="Mise à jour image vimeo">
<i class="fa fa-picture-o" aria-hidden="true"></i>
</a>
</td>
</tr>
{% endfor %}
@@ -13,6 +13,8 @@
<link rel="stylesheet" href="{{ asset('admin/AdminLTE/dist/css/AdminLTE.min.css') }}">
<link rel="stylesheet" href="{{ asset('admin/AdminLTE/dist/css/skins/skin-blue.min.css') }}">
<link rel="stylesheet" href="{{ asset('admin/AdminLTE/plugins/datatables/dataTables.bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('admin/AdminLTE/plugins/datatables/dataTables.bootstrap.css') }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.css">
<script type="text/javascript" defer="defer" src="https://extend.vimeocdn.com/ga/64189815.js"></script>
{% block css %}
@@ -58,6 +58,10 @@
style="margin-left: 5px;">
<i class="fa fa-cart-plus" aria-hidden="true"></i>
</a>
<a href="{{ path('admin_company_refresh_img',{'id':company.id}) }}" data-toggle="tooltip"
title="Mise à jour image vimeo">
<i class="fa fa-picture-o" aria-hidden="true"></i>
</a>
{% if is_granted('ROLE_ALLOWED_TO_SWITCH') %}
<a href="{{ path('company_dashboard',{'_switch_user':company.MainUser.username}) }}"
data-toggle="tooltip" title="Se connecter avec ce compte"
@@ -88,7 +92,7 @@
"language": {
"url": "https://cdn.datatables.net/plug-ins/1.10.11/i18n/French.json"
},
"order": [[1, 'desc']],
"order": [[0, 'desc']],
"columnDefs": [
{"targets": 0, "searchable": true, "orderable": true},
{"targets": 1, "searchable": true, "orderable": true},
@@ -94,7 +94,7 @@
{"targets": 4, "searchable": true, "orderable": true, "className": "text-center"},
{"targets": 5, "searchable": false, "orderable": false, "className": "text-center"},
],
"order": [[1, "asc"]]
"order": [[0, "desc"]]
});
});
</script>
@@ -29,6 +29,7 @@
{{ form_row(form.emphasisOrder) }}
{{ form_row(form.brandName) }}
{{ form_row(form.description) }}
{{ form_row(form.descriptionAdmin) }}
{{ form_row(form.website) }}
{{ form_row(form.tagsComma) }}
{{ form_row(form.file) }}
@@ -60,11 +61,24 @@
</div>
{{ form_end(form) }}
{% endblock %}
{% block css %}
<link rel="stylesheet" href="{{ asset('codemirror/lib/codemirror.css') }}">
{% endblock %}
{% block javascripts %}
<script>
$(document).ready(function () {
$('[data-toggle="popover"]').popover();
});
</script>
{% endblock %}
<script src="{{ asset('codemirror/lib/codemirror.js') }}"></script>
<script src="{{ asset('codemirror/mode/xml/xml.js') }}"></script>
<script src="{{ asset('codemirror/mode/javascript/javascript.js') }}"></script>
<script src="{{ asset('codemirror/mode/css/css.js') }}"></script>
<script src="{{ asset('codemirror/mode/vbscript/vbscript.js') }}"></script>
<script src="{{ asset('codemirror/mode/htmlmixed/htmlmixed.js') }}"></script>
<script>
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById('territory_admin_descriptionAdmin'), {
lineNumbers: true,
});
</script>
{% endblock %}
@@ -100,7 +100,7 @@
{"targets": 3, "searchable": true, "orderable": true, "className": "text-center"},
{"targets": 4, "searchable": false, "orderable": false, "className": "text-center"},
],
"order": [[1, "asc"]]
"order": [[0, "desc"]]
});
});
</script>
@@ -0,0 +1,147 @@
{% extends 'admin/base_admin.html.twig' %}
{% block contentHeader %}
<h1>
Utilisateurs
<small>Liste</small>
</h1>
<ol class="breadcrumb">
<li>
<a href="{{ path('admin_dashboard') }}">
<i class="fa fa-dashboard"></i>
Dashboard</a>
</li>
<li>Secret</li>
<li class="active">Utilisateurs</li>
</ol>
{% endblock %}
{% block content %}
<div class="box box-primary">
<div class="box-body">
<table id="user_list_table" class="table table-hover table-bordered">
<thead>
<tr>
<th class="col-md-2">Nom</th>
<th class="col-md-2">Prénom</th>
<th class="col-md-3">Email</th>
<th class="col-md-1">Rôle</th>
<th class="col-md-3">Etat</th>
<th class="col-md-1">Action</th>
</tr>
</thead>
<tbody>
{% for u in users %}
<tr>
<td>{{ u.lastname }}</td>
<td>{{ u.firstname }}</td>
<td>{{ u.email }}</td>
<td>
{% for r in u.roles %}
{% if r != "ROLE_USER" and r == "ROLE_TALENT" %}
<span class="badge bg-blue" style="font-weight: 400;">{{ r }}</span>
{% elseif r != "ROLE_USER" and r == "ROLE_COMPANY" %}
<span class="badge bg-orange" style="font-weight: 400;">{{ r }}</span>
{% endif %}
{% endfor %}
</td>
<td>
{% if u.enabled %}
Activé
{% else %}
Désactivé
<br/>
<a href="{{ path('admin_user_resend',{'id':u.id}) }}">Renvoyer le mail de confirmation</a>
{% endif %}
</td>
<td>
<a class="delete-user" href="{{ path('admin_user_delete',{'id':u.id}) }}" data-toggle="tooltip" title="Supprimer">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block javascripts %}
<script>
$(function () {
$('#user_list_table').DataTable({
"paging": true,
"lengthChange": true,
"searching": true,
"ordering": true,
"info": true,
"autoWidth": false,
"language": {
"url": "https://cdn.datatables.net/plug-ins/1.10.11/i18n/French.json"
},
"columnDefs": [
{
"targets": 0,
"searchable": true,
"orderable": true
}, {
"targets": 1,
"searchable": true,
"orderable": true
}, {
"targets": 2,
"searchable": true,
"orderable": true
}, {
"targets": 3,
"searchable": true,
"orderable": true,
"className": "text-center"
}, {
"targets": 4,
"searchable": false,
"orderable": false,
"className": "text-center"
}, {
"targets": 5,
"searchable": false,
"orderable": false,
"className": "text-center"
}
]
});
});
$(document).ready(function () {
$('[data-toggle="popover"]').popover();
$(".delete-user").confirm({
title: "Êtes vous sûr de supprimer cet utilisateur ?",
content: "Supprimer cet utilisateur supprimera, son compte, son entreprise, ses réponses, médias",
type: 'red',
boxWidth: '30%',
useBootstrap: false,
buttons: {
confirm: {
text: 'Confirmer',
action: function () {
console.log(this.$target);
location.href = this.$target.attr('href');
return true;
}
},
cancel: {
text: 'Annuler'
}
}
});
});
</script>
{% endblock %}
@@ -0,0 +1,98 @@
{% extends 'base.html.twig' %}
{% block content %}
{% if typeObject == 'Ad' %}
{% set subtitle = 'Candidature à l\'offre d\'emploi:' %}
{% set title = object.title %}
{% set route = "answer_create_ad_step2" %}
{% elseif typeObject == 'Company' %}
{% set subtitle = 'Candidature pour l\'entreprise :' %}
{% set title = object.brandName %}
{% set route = "answer_create_company_step2" %}
{% endif %}
<div class="fluid-container bg-grey-3">
<div class="container contentWrapper contentPage" id="answerPage">
<div class="row">
<div class="col s12">
<div class="center-align bg-grey-3 m-t-20">
<strong>{{ subtitle }}</strong>
<h3 class="color-blue1 m-t-10">{{ title }}</h3>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">1</span> Importez votre CV Vidéo</h4>
</div>
<div class="col s10 offset-s1 answer-dropzone">
{% include 'media/dropzone.html.twig' with {'deleting': true } %}
</div>
</div>
</div>
{{ form_start(form, {'attr': { 'id': 'form_media' } }) }}
<div class="col-content z-depth-2 p-20 m-t-40">
{{ form_row(form.status) }}
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">2</span> Ajoutez votre commentaire</h4>
</div>
<div class="col s10 offset-s1">
<div class="row">
<div class="input-field col s12">
{{ form_errors(form.comment) }}
{{ form_widget(form.comment) }}
{{ form_label(form.comment) }}
</div>
</div>
</div>
{{ form_rest(form) }}
</div>
</div>
<div class="row m-t-40">
<div class="col s10 offset-s1 center-align">
<button id="submit" class=" btn btn-large btn-default disabled" type="submit">
Envoyer ma candidature
</button><br /><br />
<a class="color-grey5" href="{{ path(routeObject,{'alias': object.alias }) }}">Annuler</a>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
{% include 'answer/answer_tuto.twig' %}
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
var routeComment = '{{ path("anwser_edit_comment", {"id": answer.getId()}) }}';
var urlDropzone = '{{ path("upload_media_answer", {"id": answer.getId()}) }}';
var urlDelete = '{{ path("delete_media_answer", {"id": answer.getId() }) }}'
var idObject = '{{ answer.getId() }}';
var typeObject = "answer";
{% if video %}
if($("#form_media").length){
$("#submit").removeClass('disabled');
$("#submit").addClass('pulse');
}
var videoExist = true;
var videoOriginal = "{{video.getOriginalUrl()}}";
var mockFile = { name: '{{video.getTitle()}}', size: '181818181', type: 'mp4', serverID: 0, accepted: true };
{% else %}
var videoExist = false;
{% endif %}
</script>
<script src="{{ asset('/js/dropzone.js') }}"></script>
<script src="{{ asset('/js/answer.js') }}"></script>
<script type="text/javascript">
{% if mustLogin == true %}
$('#submit').on('click',function(event){
event.preventDefault();
$('#modal_login').modal('open');
});
{% endif %}
</script>
{% endblock %}
@@ -0,0 +1,55 @@
{% extends 'base.html.twig' %}
{% block content %}
{% if typeObject == 'Ad' %}
{% set subtitle = 'Candidature à l\'offre d\'emploi:' %}
{% set title = object.title %}
{% set route = "answer_create_ad_step2" %}
{% elseif typeObject == 'Company' %}
{% set subtitle = 'Candidature pour l\'entreprise :' %}
{% set title = object.brandName %}
{% set route = "answer_create_company_step2" %}
{% endif %}
<div class="fluid-container bg-grey-3">
<div class="container contentWrapper contentPage">
<div class="row">
<div class="col s12">
<div class="col-content center-align m-t-20">
<strong>{{ subtitle }}</strong>
<h3 class="color-blue1 m-0 m-t-10">{{ title }}</h3>
</div>
</div>
</div>
<div class="row">
<div class="col s12 m6 ">
<div class="col-content p-15 bg-blue-1 center-align whiteColor z-depth-2 choice-answer-item">
<img src="{{ asset('img/img_popupcv/webcam_cv_video.svg')}}">
<h3>J'enregistre mon CV vidéo !</h3>
<p>Suivez nos conseils puis enregistrez votre CV vidéo directement depuis votre webcam.</p>
<a href="{{ path(route,{'id': object.id,'type': 'webcam' }) }}" class="btn btn-default white">Enregistrer mon CV vidéo</a>
</div>
</div>
<div class="col s12 m6">
<div class="col-content p-15 center-align z-depth-2 choice-answer-item bg-white">
<img src="{{ asset('img/img_popupcv/videotheque_cv_video.svg')}}">
<h3>Je possède un CV vidéo !</h3>
<p>Importez une vidéo ou séléctionnez une vidéo<br /> dans votre vidéothèque</p>
<a href="{{ path(route,{'id': object.id, 'type': 'import'}) }}" class="btn btn btn-default">Importer mon CV vidéo</a><br /><br />
<a id="link-videotheque" href="{{ route_videotheque }}">Choisir une vidéo de ma vidéothèque</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
{% if mustLogin == true %}
$('#link-videotheque').on('click',function(event){
event.preventDefault();
$('#modal_login').modal('open');
});
{% endif %}
</script>
{% endblock %}
@@ -0,0 +1,131 @@
{% extends 'base.html.twig' %}
{% block content %}
{% if typeObject == 'Ad' %}
{% set subtitle = 'Candidature à l\'offre d\'emploi:' %}
{% set title = object.title %}
{% set route = "answer_create_ad_step2" %}
{% elseif typeObject == 'Company' %}
{% set subtitle = 'Candidature pour l\'entreprise :' %}
{% set title = object.brandName %}
{% set route = "answer_create_company_step2" %}
{% endif %}
<div class="fluid-container bg-grey-3">
<div class="container contentWrapper contentPage" id="answerPage">
<div class="row">
<div class="col s12">
<div class="center-align bg-grey-3 m-t-20">
<strong>{{ subtitle }}</strong>
<h3 class="color-blue1 m-t-10">{{ title }}</h3>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">1</span> Selectionnez votre CV vidéo</h4>
</div>
<div class="col s12">
<div class="row">
<div class="col s10 offset-s1">
<div class="p-30">
{% for vid in videos %}
{% set img = "" %}
{% if vid.thumbnails.0 is defined %}
{% set img = vid.thumbnails.0.sizes.4.link %}
{% endif %}
<div class="col s4">
<div class="card">
<div class="card-image">
<div class="embed-responsive embed-responsive-16by9">
<iframe src="https://player.vimeo.com{{ vid.getCdnUrl()|replace({ "videos": "video"}) }}" width="100%" height="auto" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>
</div>
<div style="cursor:pointer;" class="card-action" data-url="https://player.vimeo.com{{ vid.getCdnUrl()|replace({ "videos": "video"}) }}" data-img="{{ img }}" data-position="top" data-tooltip="Choisir cette vidéo" href="#" data-title="{{ vid.getTitle() }}" data-id="{{ vid.getId() }}">
<a class="addExistingVideo" >
<span>{{ vid.getTitle() }}</span>
</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{{ form_start(form, {'attr': { 'id': 'form_media' } }) }}
<div class="col-content z-depth-2 p-20 m-t-40">
{{ form_row(form.status) }}
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">2</span> Ajoutez votre commentaire</h4>
</div>
<div class="col s10 offset-s1">
<div class="row">
<div class="input-field col s12">
{{ form_errors(form.comment) }}
{{ form_widget(form.comment) }}
{{ form_label(form.comment) }}
</div>
</div>
</div>
{{ form_rest(form) }}
</div>
</div>
<div class="row m-t-40">
<div class="col s10 offset-s1 center-align">
<button id="submit" class=" btn btn-large btn-default disabled" type="submit">
Envoyer ma candidature
</button><br /><br />
<a class="color-grey5" href="{{ path(routeObject,{'alias': object.alias }) }}">Annuler</a>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
{% include 'answer/answer_tuto.twig' %}
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('/js/answer.js') }}"></script>
<script type="text/javascript">
{% if mustLogin == true %}
$('#submit').on('click',function(event){
event.preventDefault();
$('#modal_login').modal('open');
});
{% endif %}
</script>
<script type="text/javascript">
$(".card-action").click(function(){
var idVideo = $(this).data("id");
var titleVideo = $(this).data("title");
var imgVideo = $(this).data("img");
var urlVideo = $(this).data("url");
var elem = $(this);
$.ajax({
type: 'POST',
url: '{{ path("link_media_answer", {"id": answer.getId()}) }}',
data: "idVideo="+idVideo,
dataType: 'html',
success: function (response) {
$(".card-action").removeClass('active');
elem.addClass('active');
Materialize.toast('Vidéo bien associé', 4000);
if($("#submit").hasClass('disabled')){
$("#submit").removeClass('disabled');
$("#submit").addClass('pulse');
}
},
error: function (response, xhr, ajaxOptions, thrownError) {
Materialize.toast('Erreur lors de l\'association de la vidéo!', 4000);
}
});
});
</script>
{% endblock %}
@@ -0,0 +1,138 @@
{% extends 'base.html.twig' %}
{% block content %}
{% if typeObject == 'Ad' %}
{% set subtitle = 'Candidature à l\'offre d\'emploi:' %}
{% set title = object.title %}
{% set route = "answer_create_ad_step2" %}
{% elseif typeObject == 'Company' %}
{% set subtitle = 'Candidature pour l\'entreprise :' %}
{% set title = object.brandName %}
{% set route = "answer_create_company_step2" %}
{% endif %}
<div class="fluid-container bg-grey-3">
<div class="container contentWrapper contentPage" id="answerPage">
<div class="row">
<div class="col s12">
<div class="center-align bg-grey-3 m-t-20">
<strong>{{ subtitle }}</strong>
<h3 class="color-blue1 m-t-10">{{ title }}</h3>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">1</span> Enregistrez votre cv vidéo</h4>
</div>
<div class="col m4 offset-m1 s12">
<video id="myCvVideo" class="video-js vjs-default-skin"></video>
<div class="video-informations-card center-align">
<p>Merci de cliquer sur l'icône <span class="vjs-icon-device-perm"></span> afin d'activer votre webcam.</p>
<p>Votre webcam activée, lancez l'enregistrement en cliquant sur le bouton rond en bas à gauche du lecteur.</p>
<p>Si vous n'êtes pas satisfait(e) de votre CV vidéo après un enregistrement, vous pouvez à tout moment recommencer l'enregistrement.</p>
<p><a class="view-tuto">Revoir le tutoriel</a></p>
</div>
</div>
<div class="col m2 hide-on-small-only">
<div class="valign-wrapper" style="align-items:center;justify-content: center;height: 300px;width:100%;">
<div style="font-size:40px;">
<i class="fa fa-arrow-right center-align" aria-hidden="true"></i>
</div>
</div>
</div>
<div class="col m4 s12">
<video id="preview" controls="true">
<span class="vjs-control-text">Play Video</span>
</video>
<div class="btnContainer center-align" style="display:none;">
<a id="saveRecord" href="#!" class="saveVideo btn btn-default">
<i class="fa fa-floppy-o" aria-hidden="true"></i>&nbsp; Télécharger mon CV Vidéo
</a>
<div class="video-informations-card">
<p>Une fois téléchargé vous pouvez glisser-déposer votre CV vidéo dans la zone prévue pour lancer le téléchargement.</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">2</span> Importez votre CV Vidéo</h4>
</div>
<div class="col s10 offset-s1 answer-dropzone">
{% include 'media/dropzone.html.twig' with {'deleting': true } %}
</div>
</div>
</div>
{{ form_start(form, {'attr': { 'id': 'form_media' } }) }}
<div class="col-content z-depth-2 p-20 m-t-40">
{{ form_row(form.status) }}
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">3</span> Ajoutez votre commentaire</h4>
</div>
<div class="col s10 offset-s1">
<div class="row">
<div class="input-field col s12">
{{ form_errors(form.comment) }}
{{ form_widget(form.comment) }}
{{ form_label(form.comment) }}
</div>
</div>
</div>
{{ form_rest(form) }}
</div>
</div>
<div class="row m-t-40">
<div class="col s10 offset-s1 center-align">
<button id="submit" class=" btn btn-large btn-default disabled" type="submit">
Envoyer ma candidature
</button><br /><br />
<a class="color-grey5" href="{{ path(routeObject,{'alias': object.alias }) }}">Annuler</a>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
{% include 'answer/answer_tuto.twig' %}
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
var routeComment = '{{ path("anwser_edit_comment", {"id": answer.getId()}) }}';
var urlDropzone = '{{ path("upload_media_answer", {"id": answer.getId()}) }}';
var urlDelete = '{{ path("delete_media_answer", {"id": answer.getId() }) }}'
var idObject = '{{ answer.getId() }}';
var typeObject = "answer";
{% if video %}
if($("#form_media").length){
$("#submit").removeClass('disabled');
$("#submit").addClass('pulse');
}
var videoExist = true;
var videoOriginal = "{{video.getOriginalUrl()}}";
var mockFile = { name: '{{video.getTitle()}}', size: '181818181', type: 'mp4', serverID: 0, accepted: true };
{% else %}
var videoExist = false;
{% endif %}
</script>
<script src="{{ asset('/js/dropzone.js') }}"></script>
<script src="{{ asset('/js/vendors/video.min.js') }}"></script>
<script src="{{ asset('/js/vendors/RecordRTC.js') }}"></script>
<script src="{{ asset('/js/vendors/videojs.record.js') }}"></script>
<script src="{{ asset('/js/vendors/jquery.browser.min.js') }}"></script>
<script src="{{ asset('/js/answer.js') }}"></script>
<script type="text/javascript">
{% if mustLogin == true %}
$('#submit').on('click',function(event){
event.preventDefault();
$('#modal_login').modal('open');
});
{% endif %}
</script>
{% endblock %}
@@ -0,0 +1,84 @@
<div id="modal-tuto" class="modal">
<div class="modal-content">
<div class="row">
<div class="col s12">
<div class="col-content">
<h3 class="color-blue1 center-align">Les conseils de Talents Tube</h3>
<div class="owl-carousel tuto-carousel">
<div class="item-tuto-webcam carousel-item">
<div class="row">
<div class="col s4 offset-s1 hide-on-med-and-down">
<img class="responsive-img" src="{{ asset('img/img_popupcv/cv_video_step_1.svg')}}" alt="">
</div>
<div class="col s11 m11 l6 offset-s1 left-align">
<strong><span class="color-blue1">30 Minutes</span> avant lenregistrement</strong>
<br /><br />
<u>Préparez un discours <strong>clair</strong> et <strong>concis</strong></u>
<br /><br />
<strong>Posez-vous les bonnes questions : <br />
<ul>
<li>Quelle est ma situation ? </li>
<li>Quelles sont mes compétences ?</li>
<li>Que puis-je apporter à lentreprise? </li>
<li>Pourquoi je souhaite rejoindre lentreprise?</li>
</ul>
</strong>
Une fois votre scénario terminé, <strong>répétez-le plusieurs fois à voix haute pour maîtriser votre sujet.</strong>
<br /><br />
Noubliez pas quen vidéo, <strong>il faut rester soi même !</strong>
</div>
</div>
</div>
<div class="item-tuto-webcam carousel-item">
<div class="row">
<div class="col s4 offset-s1 hide-on-med-and-down">
<img class="responsive-img" src="{{ asset('img/img_popupcv/cv_video_step_2.svg')}}" alt="">
</div>
<div class="col s11 m11 l6 offset-s1 left-align">
<strong><span class="color-blue1">2 Minutes</span> avant lenregistrement</strong>
<br /><br />
<u>Préparer votre lieu de tournage :</u>
<br /><br />
<ul>
<li>Privilégiez un fond <strong>neutre</strong> et <strong>clair</strong></li>
<li>Trouvez un lieu <strong>peu bruyant</strong></li>
<li>Installez-vous dans un endroit <strong>bien éclairé de préférence naturel, sans contre jour</strong></li>
<li>Portez des <strong>habits de couleurs neutres et évitez les rayures, les pois et les carreaux.</strong></li>
<li>Privilégiez un <strong>cadrage au niveau du buste</strong></li>
</ul>
</div>
</div>
</div>
<div class="item-tuto-webcam carousel-item">
<div class="row">
<div class="col s4 offset-s1 hide-on-med-and-down">
<img class="responsive-img" src="{{ asset('img/img_popupcv/cv_video_step_3.svg')}}" alt="">
</div>
<div class="col s11 m11 l6 offset-s1 left-align">
<strong><span class="color-blue1">10 secondes</span> avant lenregistrement</strong>
<br /><br />
<u>Quelques informations à savoir avant le grand bain :</u>
<br /><br />
<strong>
<ul>
<li>Le CV doit durer entre 1.30 et 2 minutes.</li>
<li>Pensez à bien articuler.</li>
<li>Évitez les euuuh et les baaah !</li>
<li>Recommencez autant de fois que nécessaire.</li>
</ul>
<br /><br />
Cest à vous !
</strong>
</div>
</div>
</div>
</div>
<div class="carousel-fixed-item right">
<a class="text close-tuto">Passer l'intro</a>
<a class="btn btn-default next-slide">suivant</a>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -30,26 +30,28 @@
{% endblock %}">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
{# OG et TC #}
{% block ogtc %}
{#Twitter Card data pour les données enrichies sur Twitter#}
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@TalentsTube">
<meta name="twitter:title" content="Talents Tube : Le 1er job board 100% vidéo">
<meta name="twitter:description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement !">
<meta name="twitter:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}">
{% if app.request.attributes.get('_route') != null %}
{% block ogtc %}
{#Twitter Card data pour les données enrichies sur Twitter#}
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@TalentsTube">
<meta name="twitter:title" content="Talents Tube : Le 1er job board 100% vidéo">
<meta name="twitter:description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement !">
<meta name="twitter:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}">
{#Open Graph data pour le partage sur les réseaux sociaux (ex Facebook..)#}
<meta property="og:title" content="Talents Tube : Le 1er job board 100% vidéo" />
<meta property="og:type" content="article" />
<meta property="og:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}" />
<meta property="og:description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement !" />
<meta property="og:site_name" content="Talents Tube" />
<meta property="og:url" content="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}" />
{#Open Graph data pour le partage sur les réseaux sociaux (ex Facebook..)#}
<meta property="og:title" content="Talents Tube : Le 1er job board 100% vidéo" />
<meta property="og:type" content="article" />
<meta property="og:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}" />
<meta property="og:description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement !" />
<meta property="og:site_name" content="Talents Tube" />
<meta property="og:url" content="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}" />
{% endblock %}
{# Canonical #}
<link rel="canonical"
href="{% block urlCanonical %}{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}{% endblock %}">
{% endblock %}
{# Canonical #}
<link rel="canonical"
href="{% block urlCanonical %}{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}{% endblock %}">
{% endif %}
{# CSS #}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Raleway:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i&amp;subset=latin-ext"
@@ -58,6 +60,7 @@
<link rel="stylesheet" href="{{ asset('css/styles.css') }}">
{% block stylesheets %}
{% endblock %}
<script type="text/javascript"> window.$crisp=[];window.CRISP_WEBSITE_ID="78ec5756-1cd5-4f3f-b0db-cb408c8171da";(function(){ d=document;s=d.createElement("script"); s.src="https://client.crisp.chat/l.js"; s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})(); </script>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
@@ -3,7 +3,13 @@
{% block dashContent %}
<div class="row bg-bordered p-20">
{% include 'company/tabs.html.twig' with {'tab':2} %}
{% if type == "spontaneous" %}
{% include 'company/tabs.html.twig' with {'tab':3} %}
{% else %}
{% include 'company/tabs.html.twig' with {'tab':2} %}
{% endif %}
<div id="reponses" class="col s12">
<table id="table-answers" class="bordered highlight responsive-table">
<thead>
@@ -20,7 +26,7 @@
<td>
<a href="{{ path('company_answer_show',{'id':answer.id }) }}">{{ answer.user.firstname }} {{ answer.user.lastname }}</a>
</td>
<td>{{ answer.ad.title }}</td>
<td>{% if answer.ad != null %}{{ answer.ad.title }} {% endif %}</td>
<td>{{ answer.cTime()|date('d-m-Y') }}</td>
<td>
{#{% if answer.notes|length <= 0 %}#}
@@ -4,7 +4,11 @@
{% block dashContent %}
<div class="row bg-bordered p-20">
<h1 class="alttitle">Réponse de {{ answer.user.firstname }} {{ answer.user.lastname }}</h1>
{% include 'company/tabs.html.twig' with {'tab':2} %}
{% if type == "spontaneous" %}
{% include 'company/tabs.html.twig' with {'tab':3} %}
{% else %}
{% include 'company/tabs.html.twig' with {'tab':2} %}
{% endif %}
<div class="col s12 m6 l6 col-padding-right">
<div class="bg-bordered inside-m">
@@ -29,6 +29,7 @@
{% block content %}
{% include 'default/flash_message.html.twig' %}
<div class="fluid-container bg-grey-3">
<div class="container">
<div id="detail-offre-video" class="row">
@@ -89,6 +90,16 @@
<p class="chip">{{ tag }}</p>
{% endfor %}
</div>
<div class="col s12 m-t-20 ">
{% if not is_granted('ROLE_COMPANY') %}
<p class="item-detail-reply center-align">
<a href="{{ path('talent_spontaneous_application_create',{'id': company.id}) }}"
class="btn btn-default">
Candidature spontanée
</a>
</p>
{% endif %}
</div>
</div>
</div>
<div id="offers" class="row">
@@ -107,6 +118,37 @@
{% if company.territories|length %}
{% include 'ad/carrousel_territory.html.twig' with {'territories': company.territories } %}
{% endif %}
{% set popup_answer_send = app.session.flashbag.get('popup_answer_send') %}
{% set popup_answer_already_send = app.session.flashbag.get('popup_answer_already_send') %}
{% if popup_answer_send is not empty %}
{% if popup_answer_send[0] == true %}
<div id="modal-answer" class="modal">
<div class="modal-content">
<div class="row">
<div class="col s12">
<div class="col-content p-30">
{% if popup_answer_already_send is not empty and popup_answer_already_send[0] == true %}
<h3 class="color-blue1 center-align">Votre candidature a bien été envoyée à {{ company.brandname }} !</h3>
<div class="col offset-s2 s8 center-align">
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/249822507"
width="100%" height="640" frameborder="0"></iframe>
</div>
</div>
<a href="{{ path('talent_dashboard') }}" class="btn btn-default m-t-20">Accéder à mon profil</a>
<br /><br />
<a class="text modal-action modal-close">Fermer</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
@@ -118,8 +160,14 @@
{{ parent() }}
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
console.log("passe");
$.get("{{ path('company_ajaxRecStat',{'id': company.id }) }}", function (data) {});
if ($('#modal-answer').length > 0) {
$('#modal-answer').modal({
dismissible: false,
ready: function(modal, trigger) {}
});
$('#modal-answer').modal('open');
}
});
</script>
{% endblock %}
@@ -106,11 +106,11 @@
$('.fa-refresh').show();
var month1 = obj.date1.getMonth();
var day1 = obj.date1.getDate();
var year1 = obj.date1.getUTCFullYear();
var year1 = obj.date1.getFullYear();
var month2 = obj.date2.getMonth();
var day2 = obj.date2.getDate();
var year2 = obj.date2.getUTCFullYear();
var date1 = (month1 + 1) + "/" + day1 + "/" + year1 +" 00:00:00";
var year2 = obj.date2.getFullYear();
var date1 = (month1 + 1) + "/" + day1 + "/" + year1 +" 00:00:01";
var date2 = (month2 + 1) +"/" + day2 + "/" + year2 +" 23:59:59";
getChartData(date1, date2);
});
@@ -1,5 +1,18 @@
<ul class="tabs">
<li class="tab col s6"><a {% if tab == 1 %}class="active"{% endif %} target="_self" href="{{ path('company_ad') }}">{{ 'company.menu.ads.label'|trans }}</a></li>
<li class="tab col s6"><a {% if tab == 2 %}class="active"{% endif %} target="_self" href="{{ path('company_answer_list') }}">{{ 'company.menu.answers.label'|trans }}</a></li>
{#<li class="tab col s4"><a {% if tab == 3 %}class="active"{% endif %} href="#favoris">{{ 'company.menu.bookmark.label'|trans }}</a></li>#}
<li class="tab col s4">
<a {% if tab == 1 %}class="active"{% endif %} target="_self"
href="{{ path('company_ad') }}">
{{ 'company.menu.ads.label'|trans }}
</a>
</li>
<li class="tab col s4">
<a {% if tab == 2 %}class="active"{% endif %} target="_self" href="{{ path('company_answer_list') }}">
{{ 'company.menu.answers.label'|trans }}
</a>
</li>
<li class="tab col s4">
<a {% if tab == 3 %}class="active"{% endif %} target="_self" href="{{ path('company_spontaneous_list') }}">
Candidatures spontanées
</a>
</li>
</ul>
@@ -48,7 +48,6 @@
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
@@ -1,4 +1,4 @@
{% extends 'base.html.twig' %}
{% extends 'base.html.twig' %}
{% block title %}{{ ad.htmlTitle|raw }}{% endblock %}
@@ -35,13 +35,17 @@
<div class="col s12 m12 l8 xl9">
{% if ad.video and ad.status != "CLOSED" %}
<div class="row m-b-0" id="adVideo">
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/{{ ad.video.cdnUrl|replace({ "/videos/": ""}) }}"
width="100%" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
{% if ad.id == 38 %}
<img class="responsive-img" src="{{asset('/img/GROUPE-ROCHER-TT.jpg')}}">
{% else %}
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/{{ ad.video.cdnUrl|replace({ "/videos/": ""}) }}"
width="100%" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
</div>
</div>
</div>
{% endif %}
{% if ad.isPromoted %}
<div class="isPromoted"><img src="{{asset('/img/offre-pourvue-gauche.png')}}" alt="promoted"></div>
{% endif %}
@@ -124,6 +128,44 @@
{% elseif ad.company.territories|length %}
{% include 'ad/carrousel_territory.html.twig' with {'territories': ad.company.territories } %}
{% endif %}
{% set popup_answer_send = app.session.flashbag.get('popup_answer_send') %}
{% set popup_answer_already_send = app.session.flashbag.get('popup_answer_already_send') %}
{% if popup_answer_send is not empty %}
{% if popup_answer_send[0] == true %}
<div id="modal-answer" class="modal">
<div class="modal-content">
<div class="row">
<div class="col s12">
<div class="col-content p-30">
{% if popup_answer_already_send is not empty and popup_answer_already_send[0] == true %}
<h3 class="color-blue1 center-align">Candidature pour {{ ad.company.brandname }} !</h3>
<div class="col offset-s2 s8 center-align">
<p>Vous avez déjà répondu à cette annonce.</p>
<a href="{{ path('talent_dashboard') }}" class="btn btn-default m-t-20">Accéder à mon profil</a>
<br /><br />
<a class="text modal-action modal-close">Fermer</a>
</div>
{% else %}
<h3 class="color-blue1 center-align">Votre candidature a bien été envoyée à {{ ad.company.brandname }} !</h3>
<div class="col offset-s2 s8 center-align">
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/249822507"
width="100%" height="640" frameborder="0"></iframe>
</div>
</div>
<a href="{{ path('talent_dashboard') }}" class="btn btn-default m-t-20">Accéder à mon profil</a>
<br /><br />
<a class="text modal-action modal-close">Fermer</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
{% block javascripts %}
@@ -133,15 +175,19 @@
$(document).ready(function(){
$('.tooltipped').tooltip();
$.get( "{{ path('ad_ajaxRecStat',{'id': ad.id }) }}", function( data ) {});
if ($('#modal-answer').length > 0) {
$('#modal-answer').modal({
dismissible: false,
ready: function(modal, trigger) {}
});
$('#modal-answer').modal('open');
}
});
</script>
{% endblock %}
{% block stylesheets %}
<script type="application/ld+json">
{{- ad.structuredData|raw -}}
{{- ad.structuredData|raw -}}
</script>
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5a095d2dd3cf90df"></script>
{% endblock %}
@@ -21,7 +21,7 @@
{% endif %}
{% endif %}
<a href="{{ path('company_show',{'alias': ad.company.alias }) }}" title="{{ ad.company.brandName }}" class="btn btn-default btn-small-grey">
Découvir l'employeur
Découvrir l'employeur
</a>
<p class="profil-name">
<a href="{{ path('company_show',{'alias': company.alias }) }}" title="{{ company.brandName }}">
@@ -1,4 +1,4 @@
{% if not app.user %}
{% if not app.user or is_granted('ROLE_TALENT_TMP')%}
<div class="header-link header-link-signin right-align">
{% if app.request.get('_route') == "fos_user_security_login" %}
{% set href = "" %}
@@ -0,0 +1,15 @@
{% if destination_login is defined %}
{% set destination = destination_login %}
{% else %}
{% set destination = path('redirect_dashboard') %}
{% endif %}
<a class="btn btn-default btn-facebook z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}?_destination={{ destination }}">Connexion avec Facebook</a>
<a class="btn btn-default btn-linkedin z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "linkedin"}) }}?_destination={{ destination }}">Connexion avec Linkedin</a>
<div class="row">
<div class="col s12">
<div class="separator-with-label">
<hr>
<label><span>ou</span></label>
</div>
</div>
</div>
@@ -41,6 +41,9 @@
<a class="white-text td-none" href="https://twitter.com/TalentsTuber" title="Twitter" target="_blank">
<i class="fa fa-twitter" aria-hidden="true"></i>
</a>
<a class="white-text td-none" href="https://www.youtube.com/channel/UCRNqiJCLAorO0aCzNQu-8ww" title="Youtube" target="_blank">
<i class="fa fa-youtube" aria-hidden="true"></i>
</a>
<a class="white-text td-none" href="https://www.linkedin.com/company/talentstube" title="Linkedin" target="_blank">
<i class="fa fa-linkedin-square" aria-hidden="true"></i>
</a>
@@ -70,4 +73,4 @@
{{ render(controller('AppBundle:SecurityModal:loginModal')) }}
</div>
</div>
{% endif %}
{% endif %}
@@ -9,12 +9,13 @@
{# VIDEO #}
<div class="col l12 m12 s12 home-content col-noPadding">
<div id="homeTeaser" class="valign-wrapper">
<h1 class="white-text center-align">1er job board <span>100% vidéo</span></h1><br />
<a data-target="modal_concept" href="#!" class="btn btn-default btn-round btn-concept modal-trigger">
Le concept en vidéo &nbsp;&nbsp;&nbsp;
<img src="{{asset('img/bouton-play.png')}}" />
</a>
<h1 class="white-text center-align">1ère plateforme pour lemploi <span>100% vidéo</span></h1><br />
<div class="link-home-head">
<a data-target="modal_concept" href="#!" class="btn btn-default btn-round btn-concept modal-trigger">
Le concept en vidéo &nbsp;&nbsp;&nbsp;
<img src="{{asset('img/bouton-play.png')}}" />
</a>
</div>
<div class="header-video-inner">
<video loop="" preload="metadata" autoplay="" id="vid" muted>
<source src="/img/home_video.mp4" type="video/mp4">
@@ -198,6 +199,7 @@
</div>
</div>
</div>
{% include 'testimony/testimony_list.html.twig' %}
</div>
<div id="modal_concept" class="modal modal-fixed-footer">
<div class="modal-content">
@@ -12,4 +12,9 @@
{% block description %}{{ page.description }}{% endblock %}
{% block content %}{{ page.content|raw }}{% endblock %}
{% block content %}
{{ page.content|raw }}
{% if isTestimony is defined %}
{% include 'testimony/testimony_list.html.twig' %}
{% endif %}
{% endblock %}
@@ -4,7 +4,9 @@
<div class="item">
<a href="{{ path('talent_show',{'alias': talent.alias }) }}"
title="{{ user.firstname }} {{ user.lastname }}">
{% if user.photo %}
{% if user.socialPicture is not null %}
<img class="circle z-depth-3" src="{{ user.socialPicture }}" alt="{{ user.firstname }} {{ user.lastname }}"/>
{% elseif user.photo %}
<img class="circle z-depth-3" src="{{ user.webPath | imagine_filter('profile_square') }}" alt="{{ user.firstname }} {{ user.lastname }}"/>
{% else %}
<img class="circle z-depth-3"
@@ -17,7 +17,7 @@
<div class="dz-error-mark"><span>✘</span></div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
{% if deleting is defined %}
<a href="javascript:undefined;" class="btn btn-default bnt-round dz-remove" data-dz-remove>Supprimer la vidéo</a>
<a href="javascript:undefined;" class="dz-remove" data-dz-remove>Supprimer la vidéo</a>
{% endif %}
</div>
</div>
@@ -5,7 +5,7 @@
{#<h1 class="alttitle">Espace offres d'emploi</h1>#}
<div class=" row bg-bordered p-20">
<ul class="tabs">
<li class="tab col s4"><a class="active" href="#reponses">Mes réponses</a></li>
<li class="tab col s4"><a class="active" href="#reponses">Mes candidatures</a></li>
</ul>
<div id="reponses" class="col s12">
<table class="bordered highlight responsive-table">
@@ -21,15 +21,18 @@
{% for a in answers %}
<tr>
<td>
{{ a.ad.title }}<br />
{% if a.ad != null %}{{ a.ad.title }}{% else %}{{ a.company.brandname }}{% endif %}<br />
{% if a.video is not null %}
<a class="waves-effect waves-light btn btn-default modalBtn" href="#" data-url="{{ a.video.cdnUrl }}">Voir la vidéo</a>
{% endif %}
</td>
<td>{{ a.uTime|date('d/m/Y') }}</td>
<td>{{ a.ad.countAnswers }}</td>
<td>
{% if a.status == "DRAFT" %}
{% if a.ad != null %} {{ a.ad.countAnswers }}{% endif %}
</td>
<td>
{% if a.status == "DRAFT" and a.ad != null %}
<a href="{{ path('talent_answer_create',{id:a.ad.id}) }}">
<i class="fa fa-pencil-square-o" aria-hidden="true"></i>
</a>
@@ -0,0 +1,227 @@
{% extends 'base.html.twig' %}
{% block content %}
<div id="wrapper" class="contentWrapper">
<div class="row">
<div class="col s8 offset-s2">
<h3>Candidature pour l'entreprise : {{ company.brandName() }}</h3>
<div class="card-panel">
<strong><b>Comment procéder ?</b></strong>
<div class="row">
<div class="col s12 m5">
<h4 class="color-blue1">Vous ne disposez pas de CV vidéo</h4>
<p>Vous pouvez enregistrer directement votre réponse si vous disposez d'une webcam en <b>cliquant
sur le bouton ci-dessous</b>.
Une fois votre vidéo enregistrée et téléchargée vous pouvez la déposer dans la zone de
téléchargement afin de valider votre réponse.</p><br/>
<a class="modal-trigger waves-effect waves-light btn btn-default" href="#modal1">Filmer mon
CV vidéo</a>
</div>
<div class="col offset-m2 s12 m5">
<h4 class="color-blue1">Vous disposez déjà d'un cv vidéo</h4>
<p>Pour répondre à cette annonce il vous suffit de glisser votre vidéo de réponse dans la
<strong><a href="#infosDropzone">zone ci-dessous</a></strong>. Une fois la vidéo
téléchargée vous pourrez valider votre réponse. Vous pouvez néanmoins laisser
un message en complément de la vidéo dans la zone prévue à cette effet plus bas.
</p>
<a class="modal-trigger waves-effect waves-light btn btn-default" href="#modal2">Choisir une
vidéo de ma vidéothèque</a>
</div>
</div>
</div>
<p></p>
{% set video = null %}
{% include 'media/dropzone.html.twig' %}
{{ form_start(form, {'attr': { 'id': 'form_media' } }) }}
{{ form_row(form.status) }}
<br/><br/>
<div class="row">
<div class="input-field col s12">
{{ form_errors(form.comment) }}
{{ form_widget(form.comment) }}
{{ form_label(form.comment) }}
</div>
</div>
<br/>
{{ form_rest(form) }}
<button id="submit" class="btn btn-large btn-default disabled" type="submit">
Valider ma réponse
</button>
{{ form_end(form) }}
<br/>
</div>
</div>
</div>
<!-- Modal Vidéotheque -->
<div id="modal2" class="modal modal-fixed-footer">
<div class="modal-content modal-choiceExistingVideo">
<h2>Choisir une vidéo existante</h2>
<div class="row">
{% for vid in videos %}
{% set img = "" %}
{% if vid.thumbnails.0 is defined %}
{% set img = vid.thumbnails.0.sizes.4.link %}
{% endif %}
<div class="col s4">
<a class="addExistingVideo tooltipped btn btn-default"
data-url="https://player.vimeo.com{{ vid.getCdnUrl()|replace({ "videos": "video"}) }}"
data-img="{{ img }}" data-position="top" data-tooltip="Choisir cette vidéo" href="#"
data-title="{{ vid.getTitle() }}" data-id="{{ vid.getId() }}">
<span class="truncate">{{ vid.getTitle() }}</span><br/>
</a>
<iframe src="https://player.vimeo.com{{ vid.getCdnUrl()|replace({ "videos": "video"}) }}"
width="100%" height="auto" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
</div>
{% endfor %}
</div>
</div>
</div>
<!-- Modal Structure -->
<div id="modal1" class="modal modal-fixed-footer">
<div class="modal-content">
<div class="row">
<div class="col m5 s12">
<h4 class="color-blue1">J'enregistre mon CV vidéo</h4>
<video id="myCvVideo" class="video-js vjs-default-skin"></video>
<div class="video-informations-card">
<p>Merci de cliquer sur l'icone <span class="vjs-icon-device-perm"></span> afin d'activer votre
webcam.</p>
<p>Votre webcam activée, lancez l'enregistrement en cliquant sur le bouton rond en bas à gauche
du lecteur.</p>
<p>Si vous n'êtes pas satisfait de votre CV vidéo après un enregistrement, vous pouvez à tout
moment recommencer l'enregistrement.</p>
</div>
</div>
<div class="col m2 hide-on-small-only">
<div class="valign-wrapper"
style="align-items:center;justify-content: center;height: 300px;width:100%;">
<div style="font-size:40px;">
<i class="fa fa-arrow-right center-align" aria-hidden="true"></i>
</div>
</div>
</div>
<div class="col m5 s12">
<h4 class="color-blue1">Je prévisualise mon CV vidéo</h4>
<video id="preview" controls="true">
<span class="vjs-control-text">Play Video</span>
</video>
<div class="btnContainer center-align" style="display:none;">
<a id="saveRecord" href="#!" class="saveVideo btn btn-default">
<i class="fa fa-floppy-o" aria-hidden="true"></i>&nbsp; Télécharger mon cv-vidéo
</a>
<div class="video-informations-card">
<p>Une fois téléchargé vous pouvez glisser-déposer votre CV-vidéo dans la zone prévue pour
lancer le téléchargement.</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action modal-close waves-effect waves-blue btn-flat ">Fermer</a>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript">
var urlDropzone = '{{ path("upload_media_answer", {"id": answer.getId()}) }}';
var urlDelete = '{{ path("delete_media_answer", {"id": answer.getId() }) }}';
var idObject = '{{ answer.getId() }}';
var typeObject = "answer";
var videoExist = false;
</script>
<script type="text/javascript">
$(".addExistingVideo").click(function () {
var idVideo = $(this).data("id");
var titleVideo = $(this).data("title");
var imgVideo = $(this).data("img");
var urlVideo = $(this).data("url");
var drop = $("#my-awesome-dropzone")[0].dropzone;
drop.removeAllFiles(true);
$.ajax({
type: 'POST',
url: '{{ path("link_media_answer", {"id": answer.getId()}) }}',
data: "idVideo=" + idVideo,
dataType: 'html',
success: function (response) {
Materialize.toast('Vidéo associé Merci', 4000);
$('#modal2').modal();
$('#modal2').modal('close');
videoOriginal = urlVideo;
videoExist = true;
var mockFile = {name: titleVideo, size: '100', type: 'mp4', serverID: 0, accepted: true};
drop.emit("addedfile", mockFile);
drop.files.push(mockFile);
iframe = '{% include "media/dropzoneTemplateSuccess.html.twig" with {"url_iframe": "#URL_PLACEHOLDER#"} only %}';
iframe = iframe.replace('#URL_PLACEHOLDER#', urlVideo);
if ($('#preview_video > iframe').length) {
$('#preview_video > iframe').attr('src', urlVideo);
$('#preview_video > *').fadeIn();
if ($("#form_media #submit").hasClass('disabled')) {
$("#form_media > #submit").removeClass('disabled');
$("#form_media > #submit").addClass('pulse');
}
} else {
$('#preview_video').html(iframe);
}
if ($("#form_media #submit").hasClass('disabled')) {
$("#form_media > #submit").removeClass('disabled');
$("#form_media > #submit").addClass('pulse');
}
},
error: function (response, xhr, ajaxOptions, thrownError) {
Materialize.toast('Erreur lors de l\'association de la vidéo!', 4000);
}
});
});
</script>
<script src="{{ asset('/js/dropzone.js') }}"></script>
<script src="{{ asset('/js/vendors/video.min.js') }}"></script>
<script src="{{ asset('/js/vendors/RecordRTC.js') }}"></script>
<script src="{{ asset('/js/vendors/videojs.record.js') }}"></script>
<script src="{{ asset('/js/vendors/jquery.browser.min.js') }}"></script>
<script language="JavaScript">
var player = videojs("myCvVideo",
{
controls: true,
width: 320,
height: 240,
plugins: {
record: {
audio: true,
video: true,
maxLength: 300,
debug: true,
videoMimeType: 'video/mp4',
}
}
});
player.on('deviceError', function () {
console.log('device error:', player.deviceErrorCode);
});
player.on('error', function (error) {
console.log('error:', error);
});
player.on('startRecord', function () {
console.log('started recording!');
});
player.on('finishRecord', function () {
$(".btnContainer").fadeIn();
var preview = document.querySelector('#preview');
var file = player.recordedData;
var agent = navigator.userAgent;
if ($.browser.mozilla) {
window.URL = window.URL || window.webkitURL;
fileURL = window.URL.createObjectURL(file);
preview.src = fileURL;
} else {
preview.src = URL.createObjectURL(file.video);
}
});
$("#saveRecord").on('click', function () {
player.recorder.saveAs({'video': 'mon-cv-talentstube'});
});
</script>
{% endblock %}
@@ -3,13 +3,20 @@
<div class="profil center-align">
{% set company = app.user.company %}
<div class="profil-picture">
{% if app.user.photo %}
{% if app.user.photo is not null %}
<img src="{{ app.user.webPath | imagine_filter('profile_square') }}"
alt="{{ app.user.firstname }} {{ app.user.lastname|first|upper }}"
class="circle responsive-img"/>
<a href="#modalProfilePicture">
<i class="fa fa-pencil" aria-hidden="true"></i>
</a>
{% elseif app.user.socialPicture is not null %}
<img src="{{ app.user.socialPicture }}"
alt="{{ app.user.firstname }} {{ app.user.lastname|first|upper }}"
class="circle responsive-img"/>
<a href="#modalProfilePicture">
<i class="fa fa-pencil" aria-hidden="true"></i>
</a>
{% else %}
<div class="circle-letters font-2">{{ app.user.firstname|first|upper }}{{ app.user.lastname|first|upper }}</div>
<a href="#modalProfilePicture">
@@ -78,7 +85,6 @@
'AppBundle:Media:profilePicture'
)) }}
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat">Fermer</a>
@@ -133,7 +133,7 @@
<div class="col s12">
<span class="bg-blue-1 text-gradient font-2 fs-20">Mes dernières offres consultées</span>
</div>
<div class="owl-carousel">
<div class="owl-carousel owl-carousel-ptalent">
{% for historyAd in historyAds %}
<div class="item">
<a href="{{ path('ad_show',{'alias': historyAd.alias }) }}"
@@ -113,10 +113,7 @@
{% block javascripts %}
{{ parent() }}
<script src="https://player.vimeo.com/api/player.js"></script>
<script>
var iframe = document.querySelector('iframe');
var player = new Vimeo.Player(iframe);
$(document).ready(function(){
$.get( "{{ path('talent_ajaxRecStat',{'id': talent.id }) }}", function( data ) {
});
@@ -95,6 +95,17 @@
</div>
</div>
</div>
{% if company.descriptionAdmin %}
<div class="col s12 m12 l8 xl9 right">
<div class="row bg-bordered">
<div class="col s12">
<div class="item-detail-description-bo">
<p>{{ company.descriptionAdmin|raw }}</p>
</div>
</div>
</div>
</div>
{% endif %}
{% if companyAds|length > 0 %}
<div id="offers" class="row">
<div class="col s12">
@@ -0,0 +1,40 @@
<div id="liste-testimony" class="bg-white">
<div class="container">
<div class="row flexcontainer row-noMargin">
<div class="owl-carousel owl-carousel-testimony">
<div class="item">
<div class="row">
<div class="col s12 l2">
<img class="circle z-depth-3" src="{{ asset('img/testimony/de-charry.jpg')}}" alt="Jean-Philippe, Gérant, cabinet de Charry"/>
</div>
<div class="col s12 l8 left-align">
<h3><strong>Jean-Philippe</strong>, Gérant, Cabinet de Charry</h3>
<p>
Notre entreprise amorce une nouvelle dynamique grâce à la vidéo de recrutement.<br />
Nous accueillons demain notre nouvel agent commercial, basé à Auray/Lorient.<br />
Il sera suivi de près par un autre très bientôt...<br />
Nous avons eu beaucoup dappréciations positives grâce à cette communication.
</p>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="col l2">
<img class="circle z-depth-3" src="{{ asset('img/testimony/lionel.jpg')}}" alt="Jean-Philippe, Gérant, cabinet de Charry"/>
</div>
<div class="col s12 l8 left-align text-testimony">
<h3><strong>Lionel</strong>, dirigeant, LB Groupe</h3>
<p>
Talents Tube nous a permis de recruter deux collaborateurs sur des profils bien spécifiques en un temps rapide.<br />
Loffre demploi vidéo a permis datteindre des candidats aux profils plus divers quune annonce classique sur papier ou web.<br />
Les CV vidéo ont permis de gagner un temps précieux au niveau de la présélection.<br />
Atout supplémentaire : nos annonces en vidéo ont contribué à développer notre marque employeur !
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -40,4 +40,5 @@ assetic:
- 'js/vendors/typeahead.js'
- 'js/company.js'
- 'js/backend.js'
- 'js/tags.js'
- 'js/tags.js'
- 'js/vendors/jquery-confirm.min.js'
+35 -1
View File
@@ -25,7 +25,9 @@ framework:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
# http://symfony.com/doc/master/deployment/proxies.html
# https://symfony.com/blog/fixing-the-trusted-proxies-configuration-for-symfony-3-3
trusted_proxies: [192.0.0.1, 10.0.0.0/8, 172.16.0.0/12]
session:
handler_id: session.handler.native_file
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
@@ -157,6 +159,38 @@ doctrine_migrations:
table_name: migration_versions
name: Application Migrations
hwi_oauth:
connect:
confirmation: false
account_connector: app.user_provider
target_path_parameter: _destination
#use_referer: true
firewall_names:
- main
fosub:
username_iterations: 30
properties:
facebook: facebookId
linkedin: linkedinId
resource_owners:
facebook:
type: facebook
client_id: 1800752833559014
client_secret: 454de729b1e58f506f94c8b50ca5c011
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:
email: email
profilepicture: picture.data.url
#csrf: true
linkedin:
type: linkedin
client_id: 86m6hegwyj8lbo
client_secret: LIOibqDszsP2vQSr
infos_url: "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,location,email-address,picture-urls::(original))?format=json"
options:
#csrf: true
# Monolog
monolog:
handlers:
@@ -30,5 +30,5 @@ monolog:
# type: chromephp
# level: info
#swiftmailer:
# delivery_addresses: ['me@example.com']
swiftmailer:
delivery_addresses: ['%delivery_addresses%']
@@ -1,17 +1,16 @@
# This file is auto-generated during the composer install
parameters:
mailer_transport: smtp
mailer_host: mail.gandi.net
mailer_user: noreply@talentstube.com
mailer_password: zfYwOGBHweCQ8OI9ghF6lUyo
secret: 416157a2389cec970df2a46fa8ffd361b76516d1
database_host: 'tt-website.postgres.dev'
database_host: tt-website.postgres.dev
database_port: '5432'
database_name: database
database_user: user
database_password: edcl56
#Mongo
mongodb_server: "mongodb://tt-website.mongo.dev:27017"
#Prestashop
mongodb_server: 'mongodb://tt-website.mongo.dev:27017'
prestashop_key: 9YUQ5jPqT4Z4x5s9B25pb1yuGBtpaeBDxpWDgicPF3CuP8F2p9aK18ZS
prestashop_path: /home/projects/prestashop1/store
prestashop_id: 1
@@ -19,11 +18,10 @@ parameters:
prestashop_month_id: 2
prestashop_ad_id: 1
prestashop_video_corporate_id: 3
prestashop_url: https://www.talentstube.com/store/
#Media
prestashop_url: 'https://www.talentstube.com/store/'
media_video_dir: '%kernel.root_dir%/../web/uploads/videos/'
media_video_url: 'http://pp-static.talentstube.com/videos/'
media_photo_dir: '%kernel.root_dir%/../web/uploads/photos/'
elastic_host: tt-website.elasticsearch.dev
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
@@ -27,3 +27,4 @@ parameters:
elastic_host: tt-website.elasticsearch.preprod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
@@ -13,7 +13,7 @@ parameters:
mongodb_server: "mongodb://tt-website.mongo.prod:27017"
#Prestashop
prestashop_key: 9YUQ5jPqT4Z4x5s9B25pb1yuGBtpaeBDxpWDgicPF3CuP8F2p9aK18ZS
prestashop_path: /home/www/website/www/store/
prestashop_path: /home/www/website/store/
prestashop_id: 1
prestashop_avoid: false
prestashop_month_id: 11
@@ -27,3 +27,4 @@ parameters:
elastic_host: tt-website.elasticsearch.prod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
+13 -1
View File
@@ -7,4 +7,16 @@ app:
type: annotation
_liip_imagine:
resource: "@LiipImagineBundle/Resources/config/routing.xml"
resource: "@LiipImagineBundle/Resources/config/routing.xml"
hwi_oauth_security:
resource: "@HWIOAuthBundle/Resources/config/routing/login.xml"
prefix: /login
hwi_oauth_connect:
resource: "@HWIOAuthBundle/Resources/config/routing/connect.xml"
prefix: /login
hwi_oauth_redirect:
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
prefix: /login
+14 -6
View File
@@ -4,6 +4,7 @@ security:
memory: ~
fos_userbundle:
id: fos_user.user_provider.username_email
#id: app.user_provider
firewalls:
dev:
@@ -12,17 +13,26 @@ security:
main:
pattern: ^/
remember_me:
secret: '%kernel.secret%'
lifetime: 14515200
path: /
always_remember_me: true
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
success_handler: redirect.after.login
# logout: true
logout:
handlers: ['edeclic.prestashop.logout']
anonymous: true
oauth:
resource_owners:
facebook: "/login/check-facebook"
linkedin: "/login/check-linkedin"
login_path: "/login"
oauth_user_provider:
service: app.user_provider
anonymous: true
switch_user:
provider: fos_userbundle
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
@@ -32,9 +42,7 @@ security:
- { path: ^/admin/config/, role: [ROLE_WEBMASTER,ROLE_SUPER_ADMIN] }
- { path: ^/talent/me/, roles: ROLE_TALENT }
- { path: ^/talent/recherche/, roles: ROLE_COMPANY }
#- { path: ^/talent/(.+)/, roles: ROLE_COMPANY }
- { path: ^/entreprise/me/, roles: ROLE_COMPANY }
- { path: ^/annonce/(.+)/repondre, roles: ROLE_TALENT }
- { path: ^/territoire/me/, roles: ROLE_TERRITORY }
encoders:
@@ -43,7 +43,7 @@ services:
# Listeners
user.registration_listener:
class: AppBundle\Utils\EventListener\RegistrationListener
arguments: ["@doctrine.orm.entity_manager","@mt.slug","@security.token_storage","@router"]
arguments: ["@doctrine.orm.entity_manager","@mt.slug","@security.token_storage","@router","@fos_user.user_manager"]
tags:
- { name: kernel.event_subscriber }
@@ -72,3 +72,6 @@ services:
class: AppBundle\Utils\Services\ProductManager
arguments: ["@doctrine.orm.entity_manager","@security.token_storage", "@app.mail_manager"]
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}]
+8 -2
View File
@@ -34,7 +34,7 @@
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
"twig/twig": "^1.0||^2.0",
"friendsofsymfony/user-bundle": "~2.0@dev",
"friendsofsymfony/user-bundle": "~2.0",
"doctrine/mongodb-odm-bundle": "^3.0",
"doctrine/mongodb-odm": "^1.0",
"alcaeus/mongo-php-adapter": "^1.0",
@@ -44,7 +44,13 @@
"vimeo/vimeo-api": "^1.1",
"pulse00/ffmpeg-bundle": "^0.6.0",
"doctrine/doctrine-migrations-bundle": "^1.0",
"nmure/crawler-detect-bundle": "^1.0.0"
"nmure/crawler-detect-bundle": "^1.0.0",
"hwi/oauth-bundle": "^0.6.0",
"php-http/guzzle6-adapter": "^1.1",
"php-http/httplug-bundle": "^1.8",
"symfony/assetic-bundle": "^2.8",
"friendsofsymfony/elastica-bundle": "4.1.*",
"liip/imagine-bundle": "^1.9"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
File diff suppressed because it is too large Load Diff
@@ -417,11 +417,12 @@ class AdController extends Controller
}
$mediaManager->getThumbnails($a);
}
$session = new Session();
return $this->render('default/ad_show.html.twig', [
'ad' => $ad,
'companyAds' => $companyAds,
'alreadyAnswered' => $alreadyAnswered
'alreadyAnswered' => $alreadyAnswered,
]);
}
@@ -10,7 +10,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class AdController extends Controller
{
@@ -111,7 +110,6 @@ class AdController extends Controller
));
}
/**
* @Route("/admin/config/ad/{id}/edit", name="admin_ad_edit")
*/
@@ -130,6 +128,16 @@ class AdController extends Controller
));
}
/**
* @Route("/admin/config/ad/{id}/refresh-img", name="admin_ad_refresh_img")
*/
public function adminAdRefreshImgAction(Request $request, Ad $ad)
{
$mediaManager = $this->get('media_manager');
$mediaManager->getThumbnails($ad, true);
return $this->redirectToRoute('admin_ad_list');
}
/**
* @Route("/admin/config/ad/{id}/show", name="admin_ad_show")
*/
@@ -12,7 +12,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class CompanyController extends Controller
{
@@ -88,4 +87,14 @@ class CompanyController extends Controller
'newP' => $newsP,
));
}
/**
* @Route("/admin/config/company/{id}/refresh-img", name="admin_company_refresh_img")
*/
public function adminCompanyRefreshImgAction(Request $request, Company $company)
{
$mediaManager = $this->get('media_manager');
$mediaManager->getThumbnails($company, true);
return $this->redirectToRoute('admin_config_company');
}
}
@@ -8,7 +8,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class TalentController extends Controller
{
@@ -11,7 +11,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
class UserController extends Controller
{
@@ -30,7 +29,7 @@ class UserController extends Controller
}
}
return $this->render('admin/user_list.html.twig', [
'users' => $users
'users' => $users,
]);
}
@@ -64,4 +63,142 @@ class UserController extends Controller
'form' => $form->createView(),
]);
}
/**
* @Route("/admin/config/user/list", name="admin_config_others_user")
*/
public function adminOthersUsersListAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$t = $em->getRepository('AppBundle:User')->findTalentsAndCompanies();
return $this->render('admin/users_list.html.twig', array(
'users' => $t,
));
}
/**
* @Route("/admin/config/user/{id}/resend", name="admin_user_resend")
*/
public function adminUserResendAction(Request $request, $id)
{
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('id' => $id));
$mailer = $this->get('fos_user.mailer');
$mailer->sendConfirmationEmailMessage($user);
return $this->redirectToRoute('admin_config_user');
}
/**
* @Route("/admin/config/user/{id}/delete", name="admin_user_delete")
*/
public function adminUserDeleteAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$t = $em->getRepository('AppBundle:User')->findByRole('ROLE_TALENT');
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('id' => $id));
if (\is_null($user)) {
// user not found, generate $notFoundResponse
$this->addFlash(
'notice',
' user not found !'
);
}
\assert(!\is_null($user));
$company = $user->getCompany();
if ($company) {
$company->setPresentationVideo(null);
$em->persist($company);
$em->flush();
}
$this->deleteRelation($user);
$em->remove($user);
$em->flush();
if ($company) {
$em->remove($company);
$em->flush();
}
// if ($company) {
// $em->remove($company);
// }
$em->flush();
return $this->redirectToRoute('admin_config_others_user');
}
public function deleteRelation($user)
{
$em = $this->getDoctrine()->getManager();
$sendMessage = $em->getRepository('AppBundle:Message')->findBy(array('sender' => $user));
if ($sendMessage) {
foreach ($sendMessage as $key => $message) {
$message->setSender(null);
$message->setAnswer(null);
}
$em->flush();
}
$recipMessage = $em->getRepository('AppBundle:Message')->findBy(array('recipient' => $user));
if ($recipMessage) {
foreach ($recipMessage as $key => $message) {
$message->setRecipient(null);
$message->setAnswer(null);
}
$em->flush();
}
$bookmarks = $em->getRepository('AppBundle:Bookmark')->findBy(array('creator' => $user));
if ($bookmarks) {
foreach ($bookmarks as $key => $bookmark) {
$em->remove($bookmark);
}
$em->flush();
}
$answers = $em->getRepository('AppBundle:Answer')->findBy(array('user' => $user));
if ($answers) {
foreach ($answers as $key => $answer) {
$em->remove($answer);
}
$em->flush();
}
$ads = $em->getRepository('AppBundle:Ad')->findBy(array('creator' => $user));
if ($ads) {
foreach ($ads as $key => $ad) {
$bms = $em->getRepository('AppBundle:BookmarkAd')->findBy(array('ad' => $ad));
foreach ($bms as $key2 => $bm) {
$em->remove($bm);
}
$em->remove($ad);
}
$em->flush();
}
$ads = $em->getRepository('AppBundle:Ad')->findBy(array('company' => $user->getCompany()));
if ($ads) {
foreach ($ads as $key => $ad) {
$bms = $em->getRepository('AppBundle:BookmarkAd')->findBy(array('ad' => $ad));
foreach ($bms as $key2 => $bm) {
$em->remove($bm);
}
$em->remove($ad);
}
$em->flush();
}
$medias = $em->getRepository('AppBundle:Media')->findBy(array('creator' => $user));
if ($medias) {
foreach ($medias as $key => $media) {
$em->remove($media);
}
$em->flush();
}
}
}
@@ -4,27 +4,284 @@ namespace AppBundle\Controller;
use AppBundle\Entity\Ad;
use AppBundle\Entity\Answer;
use AppBundle\Entity\Company;
use AppBundle\Entity\Message;
use AppBundle\Form\AnswerType;
use AppBundle\Form\ContactTalentType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\EventDispatcher\EventDispatcher,
Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken,
Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class AnswerController extends Controller
{
/**
* @Route("/anwser/edit/comment/{id}", name="anwser_edit_comment")
*/
public function anwserEditCommentAction(Request $request, Answer $answer)
{
if($answer) {
$em = $this->getDoctrine()->getManager();
$answer->setComment($request->get('comment'));
$em->persist($answer);
$em->flush();
}
return new JsonResponse(array('success' => "true"));
}
/**
* @Route("/annonce/{ad}/reponse/{answer}", name="answer_create_ad_step3")
* @Security("answer.getUser().getId() == user.getId()")
*/
public function createAnswerAdStep3Action(Request $request, Ad $ad, Answer $answer)
{
return $this->finishAnswerAction($request, $ad, $answer);
}
/**
* @Route("/company/{company}/reponse/{answer}", name="answer_create_company_step3")
* @Security("answer.getUser().getId() == user.getId()")
*/
public function createAnswerCompanyStep3Action(Request $request, Company $company, Answer $answer)
{
return $this->finishAnswerAction($request, $company, $answer);
}
public function finishAnswerAction($request, $object, $answer) {
$securityContext = $this->container->get('security.authorization_checker');
if($object instanceof Ad) {
$route = "ad_show";
$varReqAnswer = "ad";
$contact = $object->getCreator();
$title = $answer->getAd()->getTitle();
}
if($object instanceof Company) {
$route = "company_show";
$varReqAnswer = "company";
$contact = $object->getMainUser();
$title = $object->getBrandName();
}
if (!$securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {
return $this->redirectToRoute($route, array('alias' => $object->getAlias()));
}
if($answer) {
$em = $this->getDoctrine()->getManager();
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $this->getUser(), $varReqAnswer => $object));
if (!$this->getUser()->hasRole('ROLE_TALENT')) {
$em->remove($answer);
$session = new Session();
$session->getFlashBag()->add('popup_answer_not_allowed', true);
} else {
if($existAnswer && ($existAnswer->getId() !== $answer->getid())){
$em->remove($answer);
$session = new Session();
$session->getFlashBag()->add('popup_answer_already_send', true);
} else {
$session = new Session();
$session->getFlashBag()->add('popup_answer_already_send', false);
$answer->setStatus('SENDED');
$em->persist($answer);
$mediaManager = $this->get('media_manager');
$mediaManager->getThumbnails($answer);
$thumbnailsArray = $answer->getVideo()->getThumbnails();
$img = $thumbnailsArray[0]['sizes'][3]['link'];
$mailManager = $this->get('app.mail_manager');
$link = $this->generateUrl('company_answer_show', array('id' => $answer->getId()),UrlGeneratorInterface::ABSOLUTE_URL);
$mailManager->sendMail(
'Candidature TalentsTube ',
'<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:0px;" align="center"><table cellpadding="0" cellspacing="0" style="border-collapse:collapse;border-spacing:0px;" align="center"><tbody><tr><td><img alt="" src="'.$img.'" style="border:none;display:block;outline:none;text-decoration:none;width:100%;max-width:600px;height:auto;" width="600" height="auto"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>
<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:20px 35px 20px 35px;" align="left"><div class="mj-content" style="cursor:auto;color:#534F4F;font-family:Trebuchet,Helvetica,sans-serif;font-size:14px;line-height:22px;"><p>Bonjour '.$contact->getLastname().' '.$contact->getFirstname().',</p>
<p>Le talent '.$answer->getUser()->getFirstname().' '.$answer->getUser()->getLastname().' a répondu à votre annonce '.$title.'.</p></div></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>
<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px 0px 40px 0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:15px 30px;" align="center"><table cellpadding="0" cellspacing="0" style="border:none;border-radius:30px;" align="center"><tbody><tr><td style="background:#1689FB;border-radius:30px;color:#FFFFFF;cursor:auto;" align="center" valign="middle" bgcolor="#1689FB"><a class="mj-content" href="'.$link.'" style="display:inline-block;text-decoration:none;background:#1689FB;border:1px solid #1689FB;border-radius:30px;color:#FFFFFF;font-family:Trebuchet,Helvetica,sans-serif;font-size:14px;font-weight:normal;padding:15px 30px;" target="_blank">Découvrir le talent</a></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>',
$contact,
'contact_default'
);
}
}
$session->getFlashBag()->add('popup_answer_send', true);
$em->flush();
}
return $this->redirect($this->generateUrl($route, array('alias' => $object->getAlias())));
}
/**
* @Route("/annonce/{id}/repondre/{type}", name="answer_create_ad_step2")
*/
public function createAnswerAdAction(Request $request, Ad $ad, $type = 'default')
{
return $this->generateStep2($request, $ad, $type);
}
/**
* @Route("/entreprise/{id}/repondre/{type}", name="answer_create_company_step2")
*/
public function createAnswerCompanyAction(Request $request, Company $company, $type = 'default')
{
return $this->generateStep2($request, $company, $type);
}
public function generateStep2(Request $request, $object, $type) {
if($object instanceof Ad) {
$route = "ad_show";
$routeStep3 = 'answer_create_ad_step3';
$varReqAnswer = "ad";
$typeObject = "Ad";
}
if($object instanceof Company) {
$route = "company_show";
$routeStep3 = 'answer_create_company_step3';
$varReqAnswer = "company";
$typeObject = "Company";
}
$securityContext = $this->container->get('security.authorization_checker');
if (!$securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {
return $this->redirectToRoute($route, array('alias' => $object->getAlias()));
}
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $user, $varReqAnswer => $object, 'status' => 'DRAFT'));
if ($existAnswer) {
$answer = $existAnswer;
} else {
return $this->redirectToRoute($route, array('alias' => $object->getAlias()));
}
$video = $answer->getVideo();
$videos = $em->getRepository('AppBundle:Media')->findBy(array('creator' => $this->getUser()));
$form = $this->createForm(AnswerType::class, $answer);
$form->handleRequest($request);
$mustLogin = false;
if (!$user->hasRole('ROLE_TALENT')) {
$mustLogin = true;
}
if ($form->isSubmitted() && $form->isValid()) {
if(!$mustLogin){
return $this->redirect($this->generateUrl($routeStep3, array($varReqAnswer => $object->getId(), 'answer'=> $answer->getId())));
}
}
/*Definition des urls de destination pour ouath login et register*/
$destination_login = $this->generateUrl($routeStep3, array($varReqAnswer => $object->getId(), 'answer'=> $answer->getId()));
$this->get('twig')->addGlobal('destination_login', $destination_login);
$session = new Session();
$session->set('registration_destination', $destination_login);
return $this->render('answer/answer_create_'.$type.'.twig', array(
'routeObject' => $route,
'typeObject' => $typeObject,
'object' => $object,
'form' => $form->createView(),
'answer' => $answer,
'video' => $video,
'videos' => $videos,
$varReqAnswer => $object,
'mustLogin' => $mustLogin
));
}
private function createAnonymousUser() {
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->createUser();
$uniqId = uniqId();
$user->setUsername("anonym_".$uniqId);
$user->setFirstname("anonym");
$user->setLastname("anonym");
$user->setEmail("anonym_".$uniqId."@talentstube.com");
$user->setPlainPassword($uniqId);
$user->setEnabled(false);
$user->setRoles(array('ROLE_TALENT_TMP'));
$company = new Company();
$company->setAlias("anonym_".$uniqId);
$company->setType("TALENT_TMP");
$user->setCompany($company);
$userManager->updateUser($user);
$token = new UsernamePasswordToken($user, $user->getPassword(), "public", $user->getRoles());
$this->get("security.token_storage")->setToken($token);
return true;
}
/**
* @Route("/entreprise/{id}/repondre/", name="talent_spontaneous_application_create")
*/
public function talentCreateSpontaneaousAction(Request $request, Company $company)
{
$securityContext = $this->container->get('security.authorization_checker');
if (!$securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {
$this->createAnonymousUser();
}
$em = $this->getDoctrine()->getManager();
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $this->getUser(), 'company' => $company));
if ($existAnswer) {
if ($existAnswer->getStatus() == "SENDED") {
$answer = new Answer($this->getUser(), null, 'DRAFT', $company);
$em->persist($answer);
$em->flush();
} else {
$answer = $existAnswer;
}
} else {
$answer = new Answer($this->getUser(), null, 'DRAFT', $company);
$em->persist($answer);
$em->flush();
}
$em->persist($answer);
$em->flush();
$user = $this->getUser();
$mustLogin = false;
if (!$user->hasRole('ROLE_TALENT')) {
$mustLogin = true;
}
$route_videotheque = $this->generateUrl("answer_create_company_step2", array('id' => $company->getId(), 'type' => 'videotheque'));
$this->get('twig')->addGlobal('destination_login', $route_videotheque);
return $this->render('answer/answer_create_step1.html.twig', array(
'typeObject' => 'Company',
'answer' => $answer,
'object' => $company,
'mustLogin' => $mustLogin,
'route_videotheque' => $route_videotheque
));
}
/**
* @Route("/annonce/{id}/repondre/", name="talent_answer_create")
*/
public function talentCreateAnswerAction(Request $request, Ad $ad)
{
$securityContext = $this->container->get('security.authorization_checker');
if (!$securityContext->isGranted('IS_AUTHENTICATED_FULLY')) {
$this->createAnonymousUser();
}
$em = $this->getDoctrine()->getManager();
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $this->getUser(), 'ad' => $ad));
if ($existAnswer) {
if ($existAnswer->getStatus() == "SENDED") {
return $this->redirectToRoute('ad_show', array('alias' => $ad->getAlias()));
@@ -35,65 +292,37 @@ class AnswerController extends Controller
$em->persist($answer);
$em->flush();
}
$videos = $em->getRepository('AppBundle:Media')->findBy(array('creator' => $this->getUser()));
$video = $answer->getVideo();
$form = $this->createForm(AnswerType::class, $answer);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$answer = $form->getData();
$answer->setStatus('SENDED');
$em->persist($answer);
$em->flush();
$link = $this->generateUrl('company_answer_show', array('id' => $answer->getAd()->getId()),UrlGeneratorInterface::ABSOLUTE_URL);
$mediaManager = $this->get('media_manager');
$mediaManager->getThumbnails($answer);
$thumbnailsArray = $answer->getVideo()->getThumbnails();
$img = $thumbnailsArray[0]['sizes'][3]['link'];
$mailManager = $this->get('app.mail_manager');
$mailManager->sendMail(
'Candidature TalentsTube ',
'<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:0px;" align="center"><table cellpadding="0" cellspacing="0" style="border-collapse:collapse;border-spacing:0px;" align="center"><tbody><tr><td><img alt="" src="'.$img.'" style="border:none;display:block;outline:none;text-decoration:none;width:100%;max-width:600px;height:auto;" width="600" height="auto"></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>
<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:20px 35px 20px 35px;" align="left"><div class="mj-content" style="cursor:auto;color:#534F4F;font-family:Trebuchet,Helvetica,sans-serif;font-size:14px;line-height:22px;"><p>Bonjour '.$ad->getCreator()->getLastname().' '.$ad->getCreator()->getFirstname().',</p>
<p>Le talent '.$answer->getUser()->getFirstname().' '.$answer->getUser()->getLastname().' a répondu à votre annonce '.$answer->getAd()->getTitle().'.</p></div></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>
<div style="margin:0 auto;max-width:600px;background:#FFFFFF;"><table class="" cellpadding="0" cellspacing="0" style="width:100%;font-size:0px;background:#FFFFFF;" align="center"><tbody><tr><td style="text-align:center;vertical-align:top;font-size:0;padding:0px 0px 40px 0px;"><!--[if mso]>
<table border="0" cellpadding="0" cellspacing="0"><tr><td style="width:600px;">
<![endif]--><div style="vertical-align:top;display:inline-block;font-size:13px;text-align:left;width:100%;" class="mj-column-per-100" aria-labelledby="mj-column-per-100"><table width="100%"><tbody><tr><td style="font-size:0;padding:15px 30px;" align="center"><table cellpadding="0" cellspacing="0" style="border:none;border-radius:30px;" align="center"><tbody><tr><td style="background:#1689FB;border-radius:30px;color:#FFFFFF;cursor:auto;" align="center" valign="middle" bgcolor="#1689FB"><a class="mj-content" href="'.$link.'" style="display:inline-block;text-decoration:none;background:#1689FB;border:1px solid #1689FB;border-radius:30px;color:#FFFFFF;font-family:Trebuchet,Helvetica,sans-serif;font-size:14px;font-weight:normal;padding:15px 30px;" target="_blank">Découvrir le talent</a></td></tr></tbody></table></td></tr></tbody></table></div><!--[if mso]>
</td></tr></table>
<![endif]--></td></tr></tbody></table></div>',
$ad->getCreator(),
'contact_default'
);
$this->addFlash('notice', $this->get('translator')->trans('ad.answer.mail.send'));
return $this->redirectToRoute('ad_show', array('alias' => $ad->getAlias()));
$user = $this->getUser();
$mustLogin = false;
if (!$user->hasRole('ROLE_TALENT')) {
$mustLogin = true;
}
return $this->render('talent/answer_create.html.twig', array(
'form' => $form->createView(),
$route_videotheque = $this->generateUrl("answer_create_ad_step2", array('id' => $ad->getId(), 'type' => 'videotheque'));
$this->get('twig')->addGlobal('destination_login', $route_videotheque);
return $this->render('answer/answer_create_step1.html.twig', array(
'typeObject' => 'Ad',
'answer' => $answer,
'video' => $video,
'videos' => $videos,
'ad' => $ad
'object' => $ad,
'mustLogin' => $mustLogin,
'route_videotheque' => $route_videotheque
));
}
/**
* @Route("/entreprise/me/espace-oe/reponse/{id}/", name="company_answer_show")
* @Security("answer.getAd().getCompany() == user.getCompany()")
* @Security("answer.checkCompany(user.getCompany()) == true")
*/
public function companyShowAnswerAction(Request $request, Answer $answer)
{
if ($answer->getAd() == null) {
$type = 'spontaneous';
$title = $answer->getCompany()->getBrandName();
} else {
$type = 'answer';
$title = $answer->getAd()->getTitle();
}
$user = $this->getUser();
$form = $this->createForm(ContactTalentType::class);
$form->handleRequest($request);
@@ -109,15 +338,15 @@ class AnswerController extends Controller
'user' => $answer->getUser(),
));
$email = \Swift_Message::newInstance()
->setSubject('Candidature : ' . $answer->getAd()->getTitle())
->setFrom($this->getParameter('mailer_user'),$user->getEmail())
->setSubject('Candidature : ' . $title)
->setFrom($this->getParameter('mailer_user'), $user->getEmail())
->setReplyTo($user->getEmail())
->setTo($answer->getUser()->getEmail())
->setBody($htmlView, 'text/html')
->addPart($plainView, 'text/plain');
$this->get('mailer')->send($email);
$em = $this->getDoctrine()->getManager();
$messageObj = new message('Candidature : ' . $answer->getAd()->getTitle(), $message, $user, $answer->getUser(), $form['status']->getData(), $answer);
$messageObj = new message('Candidature : ' . $title, $message, $user, $answer->getUser(), $form['status']->getData(), $answer);
$em->persist($messageObj);
$em->flush();
return $this->redirectToRoute('company_answer_show', ['id' => $answer->getId()]);
@@ -125,6 +354,7 @@ class AnswerController extends Controller
return $this->render('company/answer_show.html.twig', [
'answer' => $answer,
'form' => $form->createView(),
'type' => $type,
]);
}
@@ -137,7 +367,23 @@ class AnswerController extends Controller
$em = $this->getDoctrine()->getManager();
$answers = $em->getRepository('AppBundle:Answer')->getAnswerByCompany($user->getCompany()->getId());
return $this->render('company/answer_list.html.twig', [
'answers' => $answers
'answers' => $answers,
'type' => 'answer'
]);
}
/**
* @Route("/entreprise/me/espace-oe/candidature-spontanee/", name="company_spontaneous_list")
*/
public function companyListSpontaneousAction()
{
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$answers = $em->getRepository('AppBundle:Answer')->findBy(array('company' => $user->getCompany()->getId(), 'status' => 'SENDED'));
return $this->render('company/answer_list.html.twig', [
'answers' => $answers,
'type' => 'spontaneous'
]);
}
@@ -187,7 +433,7 @@ class AnswerController extends Controller
return new JsonResponse($message);
}
/**
/**
* @Route("/media/linkAnswer/{id}", name="link_media_answer")
*/
public function mediaLinkAction(Request $request, Answer $answer)
@@ -109,12 +109,17 @@ class CompanyController extends Controller
$this->get('translator')->trans('company.account.save.title')
);
}
$formFactory = $this->container->get('fos_user.change_password.form.factory');
$formPw = $formFactory->createForm();
$formPw->setData($user);
$formPw->handleRequest($request);
if ($formPw->isSubmitted() && $formPw->isValid()) {
$userManager->updateUser($user);
$this->addFlash(
'notice',
$this->get('translator')->trans('company.account.save.title')
);
}
return $this->render('company/my_account.html.twig', [
'form' => $form->createView(),
@@ -7,6 +7,7 @@ use AppBundle\Entity\Company;
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
@@ -66,6 +67,27 @@ class DefaultController extends Controller
);
}
/**
* @Route("/redirect_dashboard", name="redirect_dashboard")
*/
public function redirect_dashboard()
{
$user = $this->getUser();
if($user){
if ($user->hasRole('ROLE_TALENT')) {
return $this->redirectToRoute('talent_dashboard');
} elseif ($user->hasRole('ROLE_COMPANY')) {
return $this->redirectToRoute('company_dashboard');
}
} else {
return $this->redirectToRoute('homepage');
}
}
/**
* @Route("/test", name="test")
*/
@@ -21,7 +21,7 @@ class NoteController extends Controller
/**
* @Route("/entreprise/me/espace-oe/reponse/{id}/note/create", name="answer_note_create")
* @Security("answer.getAd().getCompany() == user.getCompany()")
* @Security("answer.checkCompany(user.getCompany()) == true")
*/
public function CompanyCreateAnswerNoteAction(Request $request, Answer $answer)
{
@@ -188,7 +188,8 @@ class PageController extends Controller
$page = $em->getRepository('AppBundle:Page')->findOneByRef('OFFREEMPLOI');
return $this->render('default/page.html.twig', [
'page' => $page
'page' => $page,
'isTestimony' => true
]);
}
@@ -201,7 +202,8 @@ class PageController extends Controller
$page = $em->getRepository('AppBundle:Page')->findOneByRef('MARQUEEMPLOYEUR');
return $this->render('default/page.html.twig', [
'page' => $page
'page' => $page,
'isTestimony' => true
]);
}
@@ -35,11 +35,15 @@ class SecurityModalController extends Controller
$csrfToken = $this->has('security.csrf.token_manager')
? $this->get('security.csrf.token_manager')->getToken('authenticate')->getValue()
: null;
$formFactory = $this->get('fos_user.registration.form.factory');
$form = $formFactory->createForm();
return $this->render('@FOSUser/Security/loginModal.html.twig', array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => $csrfToken,
'register_form' => $form->createView()
)
);
}
@@ -173,25 +173,30 @@ class Ad
***********************/
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer", mappedBy="ad", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer", mappedBy="ad", cascade={"persist", "remove"})
*/
private $answers;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductAd", mappedBy="ad", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\ProductAd", mappedBy="ad", cascade={"persist", "remove"})
*/
private $products;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist", "remove"})
*/
private $draftNotes;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="ad", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="ad", cascade={"persist", "remove"})
*/
private $territories;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\BookmarkAd", mappedBy="ad", cascade={"persist", "remove"})
*/
private $bookmarkAds;
/***********************
* Constructor
@@ -392,9 +397,9 @@ class Ad
public function getHtmlDescription()
{
$address = $this->getAddress();
$desc = 'Découvrez la vidéo de l\'offre d\'emploi ' . $this->title . ' - ';
$desc = 'Découvrez la vidéo de l\'offre d\'emploi ' . $this->title;
if (isset($address['locality'])) {
$desc .= $address['locality'];
$desc .= ' - ' .$address['locality'];
}
if (isset($address['postal_code'])) {
$zip = substr($address['postal_code'], 0, 2);
@@ -32,9 +32,16 @@ class Answer
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ad", inversedBy="answers")
* @ORM\JoinColumn(nullable=true)
*/
private $ad;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="spontaneousApplications")
* @ORM\JoinColumn(nullable=true)
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="answers", cascade={"persist"})
*/
@@ -60,38 +67,58 @@ class Answer
private $comment;
/***********************
* OneToMany Array's
***********************/
* OneToMany Array's
***********************/
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist", "remove"})
*/
private $notes;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message", mappedBy="answer", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message", mappedBy="answer", cascade={"persist", "remove"})
*/
private $messages;
/***********************
* Constructor
***********************/
public function __construct($user = null, $ad = null, $status = null)
public function __construct($user = null, $ad = null, $status = null, $company = null)
{
$this->notes = new \Doctrine\Common\Collections\ArrayCollection();
$this->messages = new \Doctrine\Common\Collections\ArrayCollection();
$this->user = $user ;
$this->ad = $ad ;
$this->user = $user;
$this->ad = $ad;
$this->status = $status;
$this->company = $company;
}
/***********************
* Custom Functions
***********************/
public function checkCompany(Company $company)
{
if ($this->ad != null) {
$c = $this->ad->getCompany();
} elseif ($this->company != null) {
$c = $this->company;
} else {
$c = null;
}
if ($company == $c) {
return true;
} else {
return false;
}
}
/***********************
* Getters & Setters
***********************/
/**
* Get id.
*
@@ -293,4 +320,28 @@ class Answer
{
return $this->messages;
}
/**
* Set company.
*
* @param \AppBundle\Entity\Company|null $company
*
* @return Answer
*/
public function setCompany(\AppBundle\Entity\Company $company = null)
{
$this->company = $company;
return $this;
}
/**
* Get company.
*
* @return \AppBundle\Entity\Company|null
*/
public function getCompany()
{
return $this->company;
}
}
@@ -51,7 +51,7 @@ class Bookmark
***********************/
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\User", mappedBy="sharedBookmarks" ,cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\User", mappedBy="sharedBookmarks" ,cascade={"persist", "remove"})
*/
private $sharedWith;
@@ -27,7 +27,7 @@ class BookmarkAd
private $id;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist","remove"})
*/
private $notes;
@@ -42,7 +42,6 @@ class BookmarkAd
*/
private $ad;
/***********************
* Constructor
***********************/
@@ -57,7 +56,6 @@ class BookmarkAd
* Getters & Setters
***********************/
/**
* Get id.
*
@@ -48,7 +48,7 @@ class BookmarkUser
***********************/
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Note", cascade={"persist", "remove"})
*/
private $notes;
@@ -56,6 +56,13 @@ class Company
*/
private $description;
/**
* @var text
*
* @ORM\Column(name="description_admin", type="text", length=255, nullable=true)
*/
private $descriptionAdmin;
/**
* @var string
*
@@ -78,10 +85,10 @@ class Company
private $alias;
/**
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Media", cascade={"persist"})
* @ORM\JoinColumn(nullable=true)
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Media", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="presentation_video_id", nullable=true)
*/
private $presentation_video;
private $presentationVideo;
/**
* @var string
@@ -128,20 +135,24 @@ class Company
private $users;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="company", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="company", cascade={"persist", "remove"})
*/
private $ads;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="territory", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="territory", cascade={"persist", "remove"})
*/
private $territoryAds;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="company", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="company", cascade={"persist", "remove"})
*/
private $territories;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer",mappedBy="company", cascade={"persist", "remove"})
*/
private $spontaneousApplications;
/***********************
* Constructor
@@ -159,7 +170,8 @@ class Company
* Custom Function
***********************/
public function init(){
public function init()
{
$this->initAddress();
$this->initTags();
$this->initExtra();
@@ -240,8 +252,8 @@ class Company
{
$arrayPublishedAds = array();
foreach ($this->getAds() as $ad) {
if( $ad->getStatus() == "PUBLISHED") {
array_push($arrayPublishedAds, $ad);
if ($ad->getStatus() == "PUBLISHED") {
array_push($arrayPublishedAds, $ad);
}
}
@@ -262,7 +274,6 @@ class Company
* Getter & Setters
***********************/
/**
* Get id.
*
@@ -486,7 +497,7 @@ class Company
*/
public function setPresentationVideo(\AppBundle\Entity\Media $presentationVideo = null)
{
$this->presentation_video = $presentationVideo;
$this->presentationVideo = $presentationVideo;
return $this;
}
@@ -498,7 +509,7 @@ class Company
*/
public function getPresentationVideo()
{
return $this->presentation_video;
return $this->presentationVideo;
}
/**
@@ -589,7 +600,6 @@ class Company
$this->file = $file;
}
/**
* Set emphasis.
*
@@ -733,4 +743,64 @@ class Company
{
return $this->territories;
}
/**
* Add spontaneousApplication.
*
* @param \AppBundle\Entity\Answer $spontaneousApplication
*
* @return Company
*/
public function addSpontaneousApplication(\AppBundle\Entity\Answer $spontaneousApplication)
{
$this->spontaneousApplications[] = $spontaneousApplication;
return $this;
}
/**
* Remove spontaneousApplication.
*
* @param \AppBundle\Entity\Answer $spontaneousApplication
*
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeSpontaneousApplication(\AppBundle\Entity\Answer $spontaneousApplication)
{
return $this->spontaneousApplications->removeElement($spontaneousApplication);
}
/**
* Get spontaneousApplications.
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getSpontaneousApplications()
{
return $this->spontaneousApplications;
}
/**
* Set descriptionAdmin.
*
* @param string|null $descriptionAdmin
*
* @return Company
*/
public function setDescriptionAdmin($descriptionAdmin = null)
{
$this->descriptionAdmin = $descriptionAdmin;
return $this;
}
/**
* Get descriptionAdmin.
*
* @return string|null
*/
public function getDescriptionAdmin()
{
return $this->descriptionAdmin;
}
}
@@ -27,7 +27,7 @@ class ProductAd
private $id;
/**
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Product", cascade={"persist"})
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Product", cascade={"persist" , "remove"})
*/
private $product;
@@ -69,52 +69,85 @@ class User extends BaseUser
private $file;
/***********************
* OneToMany Array's
***********************/
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer",mappedBy="user", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer",mappedBy="user", cascade={"persist", "remove"})
*/
private $answers;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="creator", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="creator", cascade={"persist", "remove"})
*/
private $ads;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Product",mappedBy="user", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Product",mappedBy="user", cascade={"persist", "remove"})
*/
private $products;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Media",mappedBy="creator", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Media",mappedBy="creator", cascade={"persist", "remove"})
*/
private $medias;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Bookmark",mappedBy="creator", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Bookmark",mappedBy="creator", cascade={"persist", "remove"})
*/
private $bookmarks;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Bookmark", inversedBy="sharedWith", cascade={"persist"})
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Bookmark", inversedBy="sharedWith", cascade={"persist", "remove"})
*/
private $sharedBookmarks;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message",mappedBy="sender", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message",mappedBy="sender", cascade={"persist", "remove"})
*/
private $sendedMessages;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message",mappedBy="recipient", cascade={"persist"})
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message",mappedBy="recipient", cascade={"persist", "remove"})
*/
private $receivedMessages;
/************************
* Social Network
************************/
/**
* @ORM\Column(name="facebook_id", type="string", length=255, nullable=true)
*/
private $facebookId;
/**
* @var string
*
* @ORM\Column(name="facebook_access_token", type="text", nullable=true)
*/
private $facebookAccessToken;
/**
* @ORM\Column(name="linkedin_id", type="string", length=255, nullable=true)
*/
private $linkedinId;
/**
* @var string
*
* @ORM\Column(name="linkedin_access_token", type="text", nullable=true)
*/
private $linkedinAccessToken;
/**
* @var string
*
* @ORM\Column(name="social_picture", type="text", nullable=true)
*/
private $socialPicture;
/***********************
* Constructor
@@ -123,6 +156,7 @@ class User extends BaseUser
public function __construct()
{
parent::__construct();
parent::setUsername(uniqId());
$this->answers = new ArrayCollection();
$this->ads = new ArrayCollection();
$this->bookmarks = new ArrayCollection();
@@ -161,6 +195,22 @@ class User extends BaseUser
return null === $this->photo ? null : $this->getUploadDir() . '/' . $this->photo;
}
public function getFile()
{
return $this->file;
}
/**
* Set file
*
* @param UploadedFile $file
*
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* @param string $type
* @return array|string
@@ -218,6 +268,15 @@ class User extends BaseUser
}
}
public function setEmail($email)
{
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername($email);
return $this;
}
/***********************
* Getters & Setters
***********************/
@@ -366,6 +425,30 @@ class User extends BaseUser
return $this->status;
}
/**
* Set facebookId.
*
* @param string|null $facebookId
*
* @return User
*/
public function setFacebookId($facebookId = null)
{
$this->facebookId = $facebookId;
return $this;
}
/**
* Get facebookId.
*
* @return string|null
*/
public function getFacebookId()
{
return $this->facebookId;
}
/**
* Set company.
*
@@ -606,22 +689,6 @@ class User extends BaseUser
return $this->sharedBookmarks;
}
public function getFile()
{
return $this->file;
}
/**
* Set file
*
* @param UploadedFile $file
*
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Add sendedMessage.
*
@@ -693,4 +760,100 @@ class User extends BaseUser
{
return $this->receivedMessages;
}
/**
* Set linkedinId.
*
* @param string|null $linkedinId
*
* @return User
*/
public function setLinkedinId($linkedinId = null)
{
$this->linkedinId = $linkedinId;
return $this;
}
/**
* Get linkedinId.
*
* @return string|null
*/
public function getLinkedinId()
{
return $this->linkedinId;
}
/**
* Set socialPicture.
*
* @param string|null $socialPicture
*
* @return User
*/
public function setSocialPicture($socialPicture = null)
{
$this->socialPicture = $socialPicture;
return $this;
}
/**
* Get socialPicture.
*
* @return string|null
*/
public function getSocialPicture()
{
return $this->socialPicture;
}
/**
* Set facebookAccessToken.
*
* @param string|null $facebookAccessToken
*
* @return User
*/
public function setFacebookAccessToken($facebookAccessToken = null)
{
$this->facebookAccessToken = $facebookAccessToken;
return $this;
}
/**
* Get facebookAccessToken.
*
* @return string|null
*/
public function getFacebookAccessToken()
{
return $this->facebookAccessToken;
}
/**
* Set linkedinAccessToken.
*
* @param string|null $linkedinAccessToken
*
* @return User
*/
public function setLinkedinAccessToken($linkedinAccessToken = null)
{
$this->linkedinAccessToken = $linkedinAccessToken;
return $this;
}
/**
* Get linkedinAccessToken.
*
* @return string|null
*/
public function getLinkedinAccessToken()
{
return $this->linkedinAccessToken;
}
}
@@ -13,14 +13,15 @@ namespace AppBundle\Form\Admin;
use AppBundle\Entity\Company;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class TerritoryAdminType extends AbstractType
{
@@ -32,6 +33,7 @@ class TerritoryAdminType extends AbstractType
$builder
->add('brandName', TextType::class, array('label' => 'Nom'))
->add('description', TextType::class, array('label' => 'profile.company.description', 'required' => false))
->add('descriptionAdmin', TextareaType::class, array('label' => 'Description additionel réservé aux administrateur (Attention contenu affiché en front)', 'required' => false))
->add('website', UrlType::class, array(
'label' => 'profile.company.website',
'required' => false,
@@ -14,6 +14,16 @@ class CompanyRepository extends EntityRepository
{
public function getCompanySortByAds()
{
$qb = $this
->createQueryBuilder('c')
->andWhere('c.type = :type')
->setParameter(':type', "COMPANY")
->andWhere('c.presentationVideo IS NOT NULL')
->orderBy('c.cTime', 'DESC');
$badCompany = $qb->getQuery()->getResult();
$qb = $this
->createQueryBuilder('c')
->from('AppBundle:Ad', 'a')
@@ -21,10 +31,26 @@ class CompanyRepository extends EntityRepository
->andWhere('a.status = :status')
->orderBy('a.publishedAt', 'DESC')
->setParameter(':status', "PUBLISHED");
$firstCompany = $qb->getQuery()->getResult();
return $qb
->getQuery()
->getResult();
$mergeArray = array();
array_map(function($a, $b) use (&$mergeArray) {
if($a){
if(!isset($mergeArray[$a->getId()])) {
$mergeArray[$a->getId()] = $a;
}
}
if ($b) {
if (!isset($mergeArray[$b->getId()])) {
$mergeArray[$b->getId()] = $b;
}
}
}, $firstCompany, $badCompany);
return $mergeArray;
}
public function getTerritorySortByAds()
@@ -12,4 +12,27 @@ use Doctrine\ORM\EntityRepository;
*/
class UserRepository extends EntityRepository
{
public function findByRole($role)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where('u.roles LIKE :roles')
->setParameter('roles', '%"' . $role . '"%');
return $qb->getQuery()->getResult();
}
public function findTalentsAndCompanies()
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where('u.roles LIKE :roleT')
->orWhere('u.roles LIKE :roleC')
->setParameter('roleC', '%ROLE_COMPANY%')
->setParameter('roleT', '%ROLE_TALENT%');
return $qb->getQuery()->getResult();
}
}
@@ -0,0 +1,211 @@
<?php
namespace AppBundle\Security\Core\User;
use FOS\UserBundle\Model\UserInterface as FOSUserInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseFOSUBProvider;
use AppBundle\Entity\Company;
use AppBundle\Entity\Answer;
use AppBundle\Entity\Media;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class FOSUBUserProvider extends BaseFOSUBProvider
{
protected $container;
public function __construct($userManager, $em, $slug, $container, array $properties)
{
parent::__construct($userManager,$properties);
$this->em = $em;
$this->slugService = $slug;
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function connect(UserInterface $user, UserResponseInterface $response)
{
$isTmpUser = false;
if($this->container->get('security.token_storage')->getToken()){
$userConnected = $this->container->get('security.token_storage')->getToken()->getUser();
if ($userConnected->hasRole('ROLE_TALENT_TMP')) {
$isTmpUser = true;
$idTmpUser = $userConnected->getId();
}
}
$this->disconnect($user, $response);
$property = $this->getProperty($response);
$username = $response->getUsername(); // get the unique user identifier
$serviceName = $response->getResourceOwner()->getName();
$propertyQuery = str_replace('_', '', lcfirst(ucwords($property, '_')));
$setter = 'set' . ucfirst($serviceName) . 'Id';
$setterToken = 'set' . ucfirst($serviceName) . 'AccessToken';
$existingUser = $this->userManager->findUserBy(array($propertyQuery => $username));
if (null === $existingUser) {
$userEmail = $response->getEmail();
$existingUser = $this->userManager->findUserByEmail($userEmail);
}
if (null !== $existingUser) {
$this->disconnect($existingUser, $response);
if($isTmpUser){
$this->assignToRealAccount($userConnected, $existingUser);
$user = $existingUser;
$token = new UsernamePasswordToken($user, null, "main", $user->getRoles());
$this->container->get("security.token_storage")->setToken($token);
}
$existingUser->$setter($username);
$existingUser->$setterToken($response->getAccessToken());
$this->userManager->updateUser($existingUser);
} else {
if($isTmpUser){
$existingUser = $this->loadUserByOAuthUserResponse($response);
$this->assignToRealAccount($userConnected, $existingUser);
$existingUser->$setter($username);
$existingUser->$setterToken($response->getAccessToken());
$this->userManager->updateUser($existingUser);
} else {
$user->$setter($username);
$user->$setterToken($response->getAccessToken());
$this->userManager->updateUser($user);
}
}
}
public function assignToRealAccount($userConnected, $existingUser) {
$answers = $this->em->getRepository('AppBundle:Answer')->findBy(array('user' => $userConnected));
$medias = $this->em->getRepository('AppBundle:Media')->findBy(array('creator'=> $userConnected));
foreach ($medias as $key => $media) {
$media->setCreator($existingUser);
}
$this->em->flush();
foreach ($answers as $key => $answer) {
$answer->setUser($existingUser);
}
$this->em->flush();
$this->userManager->deleteUser($userConnected);
}
public function loadUserByUsername($username)
{
$existingUser = $this->userManager->findUserByEmail($username);
if($this->container->get('security.token_storage')->getToken()){
$userConnected = $this->container->get('security.token_storage')->getToken()->getUser();
if ($userConnected->hasRole('ROLE_TALENT_TMP')) {
$this->assignToRealAccount($userConnected, $existingUser);
}
}
return $existingUser;
}
/**
* {@inheritDoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$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();
}
$userEmail = $response->getEmail();
$user = $this->userManager->findUserByEmail($userEmail);
if($serviceName == "linkedin"){
$id = $data['id'];
$birthday = null;
$gender = null;
$userPhoto = $data['pictureUrls']['values'][0];
$username = $data['firstName']."-".$data['lastName'];
$firstname = $data['firstName'];
$lastname = $data['lastName'];
} else {
$userPhoto = 'http://graph.facebook.com/'.$data['id'].'/picture?height=200';
$birthday = \DateTime::createFromFormat ('m/d/Y', $data['birthday']);
$gender = $data['gender'];
$id = $data['id'];
$firstname = $data['first_name'];
$lastname = $data['last_name'];
}
if (null === $user) {
$user = $this->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($serviceName == "linkedin"){
$user->setLinkedinId($id);
}
if($serviceName == "facebook"){
$user->setFacebookId($id);
}
$this->userManager->updateUser($user);
if ($user->getCompany() == null) {
$company = new Company();
$slugService = $this->slugService;
$alias = $slugService->slugify($user->getId() . "-" . $user->getFirstname() . "-" . $user->getLastname());
$company->setAlias($alias);
$company->setType("TALENT");
$user->setCompany($company);
$this->userManager->updateUser($user);
}
$token = new UsernamePasswordToken($user, null, "main", $user->getRoles());
$this->container->get("security.token_storage")->setToken($token);
return $user;
} else {
if($userConnected) {
$userConnected->hasRole('ROLE_TALENT_TMP');
if ($userConnected->hasRole('ROLE_TALENT_TMP')) {
$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($serviceName == "linkedin"){
$user->setLinkedinId($id);
}
if($serviceName == "facebook"){
$user->setFacebookId($id);
}
$token = new UsernamePasswordToken($user, null, "main", $user->getRoles());
$this->container->get("security.token_storage")->setToken($token);
return $user;
}
}
}
$serviceName = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($serviceName) . 'AccessToken';
$user->$setter($response->getAccessToken());
return $user;
}
}
@@ -7,6 +7,8 @@ use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\RedirectResponse;
class RegistrationListener implements EventSubscriberInterface
{
@@ -16,12 +18,13 @@ class RegistrationListener implements EventSubscriberInterface
protected $security;
protected $router;
public function __construct($em, $slugService, $security, $router)
public function __construct($em, $slugService, $security, $router, $userManager)
{
$this->em = $em;
$this->slugService = $slugService;
$this->security = $security;
$this->router = $router;
$this->userManager = $userManager;
}
public static function getSubscribedEvents()
@@ -48,6 +51,29 @@ class RegistrationListener implements EventSubscriberInterface
$user->addRole('ROLE_COMPANY');
break;
}
$session = new Session();
if ($session->get('registration_destination')) {
$userConnected = $this->security->getToken()->getUser();
$this->em->persist($user);
$this->assignToRealAccount($userConnected, $user);
$redirection = $session->get('registration_destination');
$response = new RedirectResponse($redirection);
$event->setResponse($response);
}
}
public function assignToRealAccount($userConnected, $existingUser) {
$answers = $this->em->getRepository('AppBundle:Answer')->findBy(array('user' => $userConnected));
$medias = $this->em->getRepository('AppBundle:Media')->findBy(array('creator'=> $userConnected));
foreach ($medias as $key => $media) {
$media->setCreator($existingUser);
}
$this->em->flush();
foreach ($answers as $key => $answer) {
$answer->setUser($existingUser);
}
$this->em->flush();
$this->userManager->deleteUser($userConnected);
}
public function redirectUser(FilterUserResponseEvent $event)
@@ -28,21 +28,19 @@ class MediaManager
$this->env = $env;
}
/**
* Rename video to vimeo
*/
public function editName($video)
{
if($video){
$response = $this->vimeo->request($video->getCdnUrl(), ['name'=>$video->getTitle()], 'PATCH');
return array('success' => "true",'data' => $response);
} else {
public function editName($video)
{
if ($video) {
$response = $this->vimeo->request($video->getCdnUrl(), ['name' => $video->getTitle()], 'PATCH');
return array('success' => "true", 'data' => $response);
} else {
return array('success' => "false");
}
}
}
}
/**
* @param $entity
@@ -50,7 +48,7 @@ class MediaManager
*
* Get Thumbnail of a video (Ad or Company)
*/
public function getThumbnails($entity)
public function getThumbnails($entity, $force = false)
{
if ($entity instanceof Ad) {
$video = $entity->getVideo();
@@ -62,11 +60,11 @@ class MediaManager
} else {
return null;
}
if($video){
if ($video) {
$arrayThumb = $video->getThumbnails();
if (empty($arrayThumb[0])) {
if ($force == true || empty($arrayThumb[0])) {
$response = $this->vimeo->request($video->getCdnUrl() . '/pictures', [], 'GET');
if(!isset($response['body']['error'])){
if (!isset($response['body']['error'])) {
$video->setThumbnails($response['body']['data']);
$this->em->persist($video);
$this->em->flush();
@@ -84,7 +82,9 @@ class MediaManager
{
$video = $entity;
if (unlink($this->mediaVideoDir . $video->getOriginalUrl())) {
$response = $this->vimeo->request($video->getCdnUrl(), [], 'DELETE');
if ($this->env != "dev") {
$response = $this->vimeo->request($video->getCdnUrl(), [], 'DELETE');
}
$this->em->remove($video);
$this->em->flush();
@@ -124,12 +124,12 @@ class MediaManager
$metadata = array();
//@TODO: trouver un fix pour la duration
/*if($extension != "mkv"){
$duration = $this->ffprobe->format($filePath)->get('duration');
$metadata['duration'] = $duration;
$duration = $this->ffprobe->format($filePath)->get('duration');
$metadata['duration'] = $duration;
}*/
$thumbnails = array();
//PUSH VIDEO TO Vimeo
if ( $this->env == "dev" ) {
//PUSH VIDEO TO Vimeo
if ($this->env == "dev") {
$uriVimeo = "/videos/215657518";
$nameVimeo = "name";
$linkVimeo = "/videos/215657518";
@@ -141,8 +141,8 @@ class MediaManager
$nameVimeo = $response['body']['name'];
$linkVimeo = $response['body']['link'];
}
}
}
//SAVE MEDIA
$media->setCreator($creator);
$media->setTitle($fileName);
@@ -155,11 +155,15 @@ class MediaManager
$this->em->persist($media);
if (!is_null($entity)) {
if ($entity instanceof Answer) {
$media->setTitle("Video réponse à : ".$entity->getAd()->getTitle());
if ($entity->getAd() == null) {
$media->setTitle("Candidature pour : " . $entity->getCompany()->getBrandName());
} else {
$media->setTitle("Video réponse à : " . $entity->getAd()->getTitle());
}
$entity->setVideo($media);
$this->em->persist($entity);
} elseif ($entity instanceof Ad) {
$media->setTitle("Video annonce de : ".$entity->getTitle());
$media->setTitle("Video annonce de : " . $entity->getTitle());
$entity->setVideo($media);
$this->em->persist($entity);
} elseif ($entity instanceof User) {
@@ -169,7 +173,7 @@ class MediaManager
$this->em->persist($entity);
}
} else {
$media->setTitle("Vidéo ".$creator->getLastname()." ".$creator->getFirstname());
$media->setTitle("Vidéo " . $creator->getLastname() . " " . $creator->getFirstname());
}
if ($creator->getCompany()->getType() == "TALENT") {
$media->setStatus("TO_MODERATE");
@@ -181,14 +185,14 @@ class MediaManager
'filename' => $media->getTitle(),
'originalFilename' => $uploadedFile->getClientOriginalName(),
'uriVimeo' => str_replace('videos', 'video', $uriVimeo),
'mediaId' => $media->getId()
'mediaId' => $media->getId(),
);
} else {
$message = array('success' => 500,
'message' => "Error Upload"
'message' => "Error Upload",
);
}
return $message;
}
}
}
@@ -87,8 +87,8 @@ class StatsManager
$lineDatesLabel[] = $stringDate;
}
}
$arrByAd[$ad->getId()]['count'] ++;
}
$arrByAd[$ad->getId()]['count'] = $nbVisitTalentByAd + $nbVisitCompanyByAd + $nbVisitAnonymByAd;
$arrByAd[$ad->getId()]['object'] = $ad;
}
}
@@ -228,9 +228,9 @@ class StatsManager
$lineDatesLabel[] = $stringDate;
}
}
$arrByAd[$ad->getId()]['count'] ++;
}
}
$arrByAd[$ad->getId()]['count'] = $nbVisitTalentByAd + $nbVisitCompanyByAd + $nbVisitAnonymByAd;
$arrByAd[$ad->getId()]['object'] = $ad;
}
}
@@ -633,12 +633,6 @@ class SymfonyRequirements extends RequirementCollection
'Install and enable the <strong>mbstring</strong> extension.'
);
$this->addRecommendation(
function_exists('iconv'),
'iconv() should be available',
'Install and enable the <strong>iconv</strong> extension.'
);
$this->addRecommendation(
function_exists('utf8_decode'),
'utf8_decode() should be available',
@@ -0,0 +1,2 @@
/vendor
/composer.lock
@@ -0,0 +1,26 @@
language: php
php:
# - 5.3 # requires old distro, see below
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- hhvm # ignore errors, see below
# lock distro so new future defaults will not break the build
dist: trusty
matrix:
include:
- php: 5.3
dist: precise
allow_failures:
- php: hhvm
install:
- composer install --no-interaction
script:
- vendor/bin/phpunit --coverage-text
@@ -0,0 +1,54 @@
# Changelog
## 1.4.0 (2017-08-18)
* Feature / Fix: The `fun()` function does not pass filter parameter `null`
to underlying `stream_filter_append()` by default
(#15 by @Nyholm)
Certain filters (such as `convert.quoted-printable-encode`) do not accept
a filter parameter at all. If no explicit filter parameter is given, we no
longer pass a default `null` value.
```php
$encode = Filter\fun('convert.quoted-printable-encode');
assert('t=C3=A4st' === $encode('täst'));
```
* Add examples and improve documentation
(#13 and #20 by @clue and #18 by @Nyholm)
* Improve test suite by adding PHPUnit to require-dev,
fix HHVM build for now again and ignore future HHVM build errors,
lock Travis distro so new future defaults will not break the build
and test on PHP 7.1
(#12, #14 and #19 by @clue and #16 by @Nyholm)
## 1.3.0 (2015-11-08)
* Feature: Support accessing built-in filters as callbacks
(#5 by @clue)
```php
$fun = Filter\fun('zlib.deflate');
$ret = $fun('hello') . $fun('world') . $fun();
assert('helloworld' === gzinflate($ret));
```
## 1.2.0 (2015-10-23)
* Feature: Invoke close event when closing filter (flush buffer)
(#9 by @clue)
## 1.1.0 (2015-10-22)
* Feature: Abort filter operation when catching an Exception
(#10 by @clue)
* Feature: Additional safeguards to prevent filter state corruption
(#7 by @clue)
## 1.0.0 (2015-10-18)
* First tagged release
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Christian Lück
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,297 @@
# clue/stream-filter [![Build Status](https://travis-ci.org/clue/php-stream-filter.svg?branch=master)](https://travis-ci.org/clue/php-stream-filter)
A simple and modern approach to stream filtering in PHP
**Table of contents**
* [Why?](#why)
* [Usage](#usage)
* [append()](#append)
* [prepend()](#prepend)
* [fun()](#fun)
* [remove()](#remove)
* [Install](#install)
* [Tests](#tests)
* [License](#license)
## Why?
PHP's stream filtering system is great!
It offers very powerful stream filtering options and comes with a useful set of built-in filters.
These filters can be used to easily and efficiently perform various transformations on-the-fly, such as:
* read from a gzip'ed input file,
* transcode from ISO-8859-1 (Latin1) to UTF-8,
* write to a bzip output file
* and much more.
But let's face it:
Its API is [*difficult to work with*](http://php.net/manual/en/php-user-filter.filter.php)
and its documentation is [*subpar*](http://stackoverflow.com/questions/27103269/what-is-a-bucket-brigade).
This combined means its powerful features are often neglected.
This project aims to make these features more accessible to a broader audience.
* **Lightweight, SOLID design** -
Provides a thin abstraction that is [*just good enough*](http://en.wikipedia.org/wiki/Principle_of_good_enough)
and does not get in your way.
Custom filters require trivial effort.
* **Good test coverage** -
Comes with an automated tests suite and is regularly tested in the *real world*
## Usage
This lightweight library consists only of a few simple functions.
All functions reside under the `Clue\StreamFilter` namespace.
The below examples assume you use an import statement similar to this:
```php
use Clue\StreamFilter as Filter;
Filter\append();
```
Alternatively, you can also refer to them with their fully-qualified name:
```php
\Clue\StreamFilter\append();
```
### append()
The `append($stream, $callback, $read_write = STREAM_FILTER_ALL)` function can be used to
append a filter callback to the given stream.
Each stream can have a list of filters attached.
This function appends a filter to the end of this list.
This function returns a filter resource which can be passed to [`remove()`](#remove).
If the given filter can not be added, it throws an `Exception`.
The `$stream` can be any valid stream resource, such as:
```php
$stream = fopen('demo.txt', 'w+');
```
The `$callback` should be a valid callable function which accepts an individual chunk of data
and should return the updated chunk:
```php
$filter = Filter\append($stream, function ($chunk) {
// will be called each time you read or write a $chunk to/from the stream
return $chunk;
});
```
As such, you can also use native PHP functions or any other `callable`:
```php
Filter\append($stream, 'strtoupper');
// will write "HELLO" to the underlying stream
fwrite($stream, 'hello');
```
If the `$callback` accepts invocation without parameters, then this signature
will be invoked once ending (flushing) the filter:
```php
Filter\append($stream, function ($chunk = null) {
if ($chunk === null) {
// will be called once ending the filter
return 'end';
}
// will be called each time you read or write a $chunk to/from the stream
return $chunk;
});
fclose($stream);
```
> Note: Legacy PHP versions (PHP < 5.4) do not support passing additional data
from the end signal handler if the stream is being closed.
If your callback throws an `Exception`, then the filter process will be aborted.
In order to play nice with PHP's stream handling, the `Exception` will be
transformed to a PHP warning instead:
```php
Filter\append($stream, function ($chunk) {
throw new \RuntimeException('Unexpected chunk');
});
// raises an E_USER_WARNING with "Error invoking filter: Unexpected chunk"
fwrite($stream, 'hello');
```
The optional `$read_write` parameter can be used to only invoke the `$callback` when either writing to the stream or only when reading from the stream:
```php
Filter\append($stream, function ($chunk) {
// will be called each time you write to the stream
return $chunk;
}, STREAM_FILTER_WRITE);
Filter\append($stream, function ($chunk) {
// will be called each time you read from the stream
return $chunk;
}, STREAM_FILTER_READ);
```
> Note that once a filter has been added to stream, the stream can no longer be passed to
> [`stream_select()`](http://php.net/manual/en/function.stream-select.php)
> (and family).
>
> > Warning: stream_select(): cannot cast a filtered stream on this system in {file} on line {line}
>
> This is due to limitations of PHP's stream filter support, as it can no longer reliably
> tell when the underlying stream resource is actually ready.
> As an alternative, consider calling `stream_select()` on the unfiltered stream and
> then pass the unfiltered data through the [`fun()`](#fun) function.
### prepend()
The `prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)` function can be used to
prepend a filter callback to the given stream.
Each stream can have a list of filters attached.
This function prepends a filter to the start of this list.
This function returns a filter resource which can be passed to [`remove()`](#remove).
If the given filter can not be added, it throws an `Exception`.
```php
$filter = Filter\prepend($stream, function ($chunk) {
// will be called each time you read or write a $chunk to/from the stream
return $chunk;
});
```
Except for the position in the list of filters, this function behaves exactly
like the [`append()`](#append) function.
For more details about its behavior, see also the [`append()`](#append) function.
### fun()
The `fun($filter, $parameters = null)` function can be used to
create a filter function which uses the given built-in `$filter`.
PHP comes with a useful set of [built-in filters](http://php.net/manual/en/filters.php).
Using `fun()` makes accessing these as easy as passing an input string to filter
and getting the filtered output string.
```php
$fun = Filter\fun('string.rot13');
assert('grfg' === $fun('test'));
assert('test' === $fun($fun('test'));
```
Please note that not all filter functions may be available depending on installed
PHP extensions and the PHP version in use.
In particular, [HHVM](http://hhvm.com/) may not offer the same filter functions
or parameters as Zend PHP.
Accessing an unknown filter function will result in a `RuntimeException`:
```php
Filter\fun('unknown'); // throws RuntimeException
```
Some filters may accept or require additional filter parameters most
filters do not require filter parameters.
If given, the optional `$parameters` argument will be passed to the
underlying filter handler as-is.
In particular, note how *not passing* this parameter at all differs from
explicitly passing a `null` value (which many filters do not accept).
Please refer to the individual filter definition for more details.
For example, the `string.strip_tags` filter can be invoked like this:
```php
$fun = Filter\fun('string.strip_tags', '<a><b>');
$ret = $fun('<b>h<br>i</b>');
assert('<b>hi</b>' === $ret);
```
Under the hood, this function allocates a temporary memory stream, so it's
recommended to clean up the filter function after use.
Also, some filter functions (in particular the
[zlib compression filters](http://php.net/manual/en/filters.compression.php))
may use internal buffers and may emit a final data chunk on close.
The filter function can be closed by invoking without any arguments:
```php
$fun = Filter\fun('zlib.deflate');
$ret = $fun('hello') . $fun('world') . $fun();
assert('helloworld' === gzinflate($ret));
```
The filter function must not be used anymore after it has been closed.
Doing so will result in a `RuntimeException`:
```php
$fun = Filter\fun('string.rot13');
$fun();
$fun('test'); // throws RuntimeException
```
> Note: If you're using the zlib compression filters, then you should be wary
about engine inconsistencies between different PHP versions and HHVM.
These inconsistencies exist in the underlying PHP engines and there's little we
can do about this in this library.
[Our test suite](tests/) contains several test cases that exhibit these issues.
If you feel some test case is missing or outdated, we're happy to accept PRs! :)
### remove()
The `remove($filter)` function can be used to
remove a filter previously added via [`append()`](#append) or [`prepend()`](#prepend).
```php
$filter = Filter\append($stream, function () {
// …
});
Filter\remove($filter);
```
## Install
The recommended way to install this library is [through Composer](https://getcomposer.org).
[New to Composer?](https://getcomposer.org/doc/00-intro.md)
This will install the latest supported version:
```bash
$ composer require clue/stream-filter:^1.4
```
See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
This project aims to run on any platform and thus does not require any PHP
extensions and supports running on legacy PHP 5.3 through current PHP 7+ and
HHVM.
It's *highly recommended to use PHP 7+* for this project.
Older PHP versions may suffer from a number of inconsistencies documented above.
## Tests
To run the test suite, you first need to clone this repo and then install all
dependencies [through Composer](http://getcomposer.org):
```bash
$ composer install
```
To run the test suite, go to the project root and run:
```bash
$ php vendor/bin/phpunit
```
## License
MIT
@@ -0,0 +1,23 @@
{
"name": "clue/stream-filter",
"description": "A simple and modern approach to stream filtering in PHP",
"keywords": ["stream", "callback", "filter", "php_user_filter", "stream_filter_append", "stream_filter_register", "bucket brigade"],
"homepage": "https://github.com/clue/php-stream-filter",
"license": "MIT",
"authors": [
{
"name": "Christian Lück",
"email": "christian@lueck.tv"
}
],
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^4.8"
},
"autoload": {
"psr-4": { "Clue\\StreamFilter\\": "src/" },
"files": [ "src/functions.php" ]
}
}
@@ -0,0 +1,29 @@
<?php
// $ echo test | php examples/base64_encode.php | php examples/base64_decode.php
require __DIR__ . '/../vendor/autoload.php';
// decoding requires buffering in chunks of 4 bytes each
$buffer = '';
Clue\StreamFilter\append(STDIN, function ($chunk = null) use (&$buffer) {
if ($chunk === null) {
if (strlen($buffer) % 4 !== 0) {
throw new \UnexpectedValueException('Invalid length');
}
$chunk = $buffer;
} else {
$buffer .= $chunk;
$len = strlen($buffer) - (strlen($buffer) % 4);
$chunk = (string)substr($buffer, 0, $len);
$buffer = (string)substr($buffer, $len);
}
$ret = base64_decode($chunk, true);
if ($ret === false) {
throw new \UnexpectedValueException('Not a valid base64 encoded chunk');
}
return $ret;
}, STREAM_FILTER_READ);
fpassthru(STDIN);
@@ -0,0 +1,21 @@
<?php
// $ echo test | php examples/base64_encode.php | base64 --decode
require __DIR__ . '/../vendor/autoload.php';
// encoding requires buffering in chunks of 3 bytes each
$buffer = '';
Clue\StreamFilter\append(STDIN, function ($chunk = null) use (&$buffer) {
if ($chunk === null) {
return base64_encode($buffer);
}
$buffer .= $chunk;
$len = strlen($buffer) - (strlen($buffer) % 3);
$chunk = substr($buffer, 0, $len);
$buffer = substr($buffer, $len);
return base64_encode($chunk);
}, STREAM_FILTER_READ);
fpassthru(STDIN);
@@ -0,0 +1,9 @@
<?php
// $ echo test | php examples/uppercase.php
require __DIR__ . '/../vendor/autoload.php';
Clue\StreamFilter\append(STDIN, 'strtoupper');
fpassthru(STDIN);
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite>
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/</directory>
</whitelist>
</filter>
</phpunit>
@@ -0,0 +1,120 @@
<?php
namespace Clue\StreamFilter;
use php_user_filter;
use InvalidArgumentException;
use ReflectionFunction;
use Exception;
/**
*
* @internal
* @see append()
* @see prepend()
*/
class CallbackFilter extends php_user_filter
{
private $callback;
private $closed = true;
private $supportsClose = false;
public function onCreate()
{
$this->closed = false;
if (!is_callable($this->params)) {
throw new InvalidArgumentException('No valid callback parameter given to stream_filter_(append|prepend)');
}
$this->callback = $this->params;
// callback supports end event if it accepts invocation without arguments
$ref = new ReflectionFunction($this->callback);
$this->supportsClose = ($ref->getNumberOfRequiredParameters() === 0);
return true;
}
public function onClose()
{
$this->closed = true;
// callback supports closing and is not already closed
if ($this->supportsClose) {
$this->supportsClose = false;
// invoke without argument to signal end and discard resulting buffer
try {
call_user_func($this->callback);
} catch (Exception $ignored) {
// this might be called during engine shutdown, so it's not safe
// to raise any errors or exceptions here
// trigger_error('Error closing filter: ' . $ignored->getMessage(), E_USER_WARNING);
}
}
$this->callback = null;
}
public function filter($in, $out, &$consumed, $closing)
{
// concatenate whole buffer from input brigade
$data = '';
while ($bucket = stream_bucket_make_writeable($in)) {
$consumed += $bucket->datalen;
$data .= $bucket->data;
}
// skip processing callback that already ended
if ($this->closed) {
return PSFS_FEED_ME;
}
// only invoke filter function if buffer is not empty
// this may skip flushing a closing filter
if ($data !== '') {
try {
$data = call_user_func($this->callback, $data);
} catch (Exception $e) {
// exception should mark filter as closed
$this->onClose();
trigger_error('Error invoking filter: ' . $e->getMessage(), E_USER_WARNING);
return PSFS_ERR_FATAL;
}
}
// mark filter as closed after processing closing chunk
if ($closing) {
$this->closed = true;
// callback supports closing and is not already closed
if ($this->supportsClose) {
$this->supportsClose = false;
// invoke without argument to signal end and append resulting buffer
try {
$data .= call_user_func($this->callback);
} catch (Exception $e) {
trigger_error('Error ending filter: ' . $e->getMessage(), E_USER_WARNING);
return PSFS_ERR_FATAL;
}
}
}
if ($data !== '') {
// create a new bucket for writing the resulting buffer to the output brigade
// reusing an existing bucket turned out to be bugged in some environments (ancient PHP versions and HHVM)
$bucket = @stream_bucket_new($this->stream, $data);
// legacy PHP versions (PHP < 5.4) do not support passing data from the event signal handler
// because closing the stream invalidates the stream and its stream bucket brigade before
// invoking the filter close handler.
if ($bucket !== false) {
stream_bucket_append($out, $bucket);
}
}
return PSFS_PASS_ON;
}
}
@@ -0,0 +1,146 @@
<?php
namespace Clue\StreamFilter;
use RuntimeException;
/**
* append a callback filter to the given stream
*
* @param resource $stream
* @param callable $callback
* @param int $read_write
* @return resource filter resource which can be used for `remove()`
* @throws Exception on error
* @uses stream_filter_append()
*/
function append($stream, $callback, $read_write = STREAM_FILTER_ALL)
{
$ret = @stream_filter_append($stream, register(), $read_write, $callback);
if ($ret === false) {
$error = error_get_last() + array('message' => '');
throw new RuntimeException('Unable to append filter: ' . $error['message']);
}
return $ret;
}
/**
* prepend a callback filter to the given stream
*
* @param resource $stream
* @param callable $callback
* @param int $read_write
* @return resource filter resource which can be used for `remove()`
* @throws Exception on error
* @uses stream_filter_prepend()
*/
function prepend($stream, $callback, $read_write = STREAM_FILTER_ALL)
{
$ret = @stream_filter_prepend($stream, register(), $read_write, $callback);
if ($ret === false) {
$error = error_get_last() + array('message' => '');
throw new RuntimeException('Unable to prepend filter: ' . $error['message']);
}
return $ret;
}
/**
* Creates filter fun (function) which uses the given built-in $filter
*
* Some filters may accept or require additional filter parameters most
* filters do not require filter parameters.
* If given, the optional `$parameters` argument will be passed to the
* underlying filter handler as-is.
* In particular, note how *not passing* this parameter at all differs from
* explicitly passing a `null` value (which many filters do not accept).
* Please refer to the individual filter definition for more details.
*
* @param string $filter built-in filter name. See stream_get_filters() or http://php.net/manual/en/filters.php
* @param mixed $parameters (optional) parameters to pass to the built-in filter as-is
* @return callable a filter callback which can be append()'ed or prepend()'ed
* @throws RuntimeException on error
* @link http://php.net/manual/en/filters.php
* @see stream_get_filters()
* @see append()
*/
function fun($filter, $parameters = null)
{
$fp = fopen('php://memory', 'w');
if (func_num_args() === 1) {
$filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE);
} else {
$filter = @stream_filter_append($fp, $filter, STREAM_FILTER_WRITE, $parameters);
}
if ($filter === false) {
fclose($fp);
$error = error_get_last() + array('message' => '');
throw new RuntimeException('Unable to access built-in filter: ' . $error['message']);
}
// append filter function which buffers internally
$buffer = '';
append($fp, function ($chunk) use (&$buffer) {
$buffer .= $chunk;
// always return empty string in order to skip actually writing to stream resource
return '';
}, STREAM_FILTER_WRITE);
$closed = false;
return function ($chunk = null) use ($fp, $filter, &$buffer, &$closed) {
if ($closed) {
throw new \RuntimeException('Unable to perform operation on closed stream');
}
if ($chunk === null) {
$closed = true;
$buffer = '';
fclose($fp);
return $buffer;
}
// initialize buffer and invoke filters by attempting to write to stream
$buffer = '';
fwrite($fp, $chunk);
// buffer now contains everything the filter function returned
return $buffer;
};
}
/**
* remove a callback filter from the given stream
*
* @param resource $filter
* @return boolean true on success or false on error
* @throws Exception on error
* @uses stream_filter_remove()
*/
function remove($filter)
{
if (@stream_filter_remove($filter) === false) {
throw new RuntimeException('Unable to remove given filter');
}
}
/**
* registers the callback filter and returns the resulting filter name
*
* There should be little reason to call this function manually.
*
* @return string filter name
* @uses CallbackFilter
*/
function register()
{
static $registered = null;
if ($registered === null) {
$registered = 'stream-callback';
stream_filter_register($registered, __NAMESPACE__ . '\CallbackFilter');
}
return $registered;
}
@@ -0,0 +1,386 @@
<?php
use Clue\StreamFilter;
class FilterTest extends PHPUnit_Framework_TestCase
{
public function testAppendSimpleCallback()
{
$stream = $this->createStream();
StreamFilter\append($stream, function ($chunk) {
return strtoupper($chunk);
});
fwrite($stream, 'hello');
fwrite($stream, 'world');
rewind($stream);
$this->assertEquals('HELLOWORLD', stream_get_contents($stream));
fclose($stream);
}
public function testAppendNativePhpFunction()
{
$stream = $this->createStream();
StreamFilter\append($stream, 'strtoupper');
fwrite($stream, 'hello');
fwrite($stream, 'world');
rewind($stream);
$this->assertEquals('HELLOWORLD', stream_get_contents($stream));
fclose($stream);
}
public function testAppendChangingChunkSize()
{
$stream = $this->createStream();
StreamFilter\append($stream, function ($chunk) {
return str_replace(array('a','e','i','o','u'), '', $chunk);
});
fwrite($stream, 'hello');
fwrite($stream, 'world');
rewind($stream);
$this->assertEquals('hllwrld', stream_get_contents($stream));
fclose($stream);
}
public function testAppendReturningEmptyStringWillNotPassThrough()
{
$stream = $this->createStream();
StreamFilter\append($stream, function ($chunk) {
return '';
});
fwrite($stream, 'hello');
fwrite($stream, 'world');
rewind($stream);
$this->assertEquals('', stream_get_contents($stream));
fclose($stream);
}
public function testAppendEndEventCanBeBufferedOnClose()
{
if (PHP_VERSION < 5.4) $this->markTestSkipped('Not supported on legacy PHP');
$stream = $this->createStream();
StreamFilter\append($stream, function ($chunk = null) {
if ($chunk === null) {
// this signals the end event
return '!';
}
return $chunk . ' ';
}, STREAM_FILTER_WRITE);
$buffered = '';
StreamFilter\append($stream, function ($chunk) use (&$buffered) {
$buffered .= $chunk;
return '';
});
fwrite($stream, 'hello');
fwrite($stream, 'world');
fclose($stream);
$this->assertEquals('hello world !', $buffered);
}
public function testAppendEndEventWillBeCalledOnRemove()
{
$stream = $this->createStream();
$ended = false;
$filter = StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
if ($chunk === null) {
$ended = true;
}
return $chunk;
}, STREAM_FILTER_WRITE);
$this->assertEquals(0, $ended);
StreamFilter\remove($filter);
$this->assertEquals(1, $ended);
}
public function testAppendEndEventWillBeCalledOnClose()
{
$stream = $this->createStream();
$ended = false;
StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
if ($chunk === null) {
$ended = true;
}
return $chunk;
}, STREAM_FILTER_WRITE);
$this->assertEquals(0, $ended);
fclose($stream);
$this->assertEquals(1, $ended);
}
public function testAppendWriteOnly()
{
$stream = $this->createStream();
$invoked = 0;
StreamFilter\append($stream, function ($chunk) use (&$invoked) {
++$invoked;
return $chunk;
}, STREAM_FILTER_WRITE);
fwrite($stream, 'a');
fwrite($stream, 'b');
fwrite($stream, 'c');
rewind($stream);
$this->assertEquals(3, $invoked);
$this->assertEquals('abc', stream_get_contents($stream));
fclose($stream);
}
public function testAppendReadOnly()
{
$stream = $this->createStream();
$invoked = 0;
StreamFilter\append($stream, function ($chunk) use (&$invoked) {
++$invoked;
return $chunk;
}, STREAM_FILTER_READ);
fwrite($stream, 'a');
fwrite($stream, 'b');
fwrite($stream, 'c');
rewind($stream);
$this->assertEquals(0, $invoked);
$this->assertEquals('abc', stream_get_contents($stream));
$this->assertEquals(1, $invoked);
fclose($stream);
}
public function testOrderCallingAppendAfterPrepend()
{
$stream = $this->createStream();
StreamFilter\append($stream, function ($chunk) {
return '[' . $chunk . ']';
}, STREAM_FILTER_WRITE);
StreamFilter\prepend($stream, function ($chunk) {
return '(' . $chunk . ')';
}, STREAM_FILTER_WRITE);
fwrite($stream, 'hello');
rewind($stream);
$this->assertEquals('[(hello)]', stream_get_contents($stream));
fclose($stream);
}
public function testRemoveFilter()
{
$stream = $this->createStream();
$first = StreamFilter\append($stream, function ($chunk) {
return $chunk . '?';
}, STREAM_FILTER_WRITE);
StreamFilter\append($stream, function ($chunk) {
return $chunk . '!';
}, STREAM_FILTER_WRITE);
StreamFilter\remove($first);
fwrite($stream, 'hello');
rewind($stream);
$this->assertEquals('hello!', stream_get_contents($stream));
fclose($stream);
}
public function testAppendFunDechunk()
{
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (dechunk filter does not exist)');
$stream = $this->createStream();
StreamFilter\append($stream, StreamFilter\fun('dechunk'), STREAM_FILTER_WRITE);
fwrite($stream, "2\r\nhe\r\n");
fwrite($stream, "3\r\nllo\r\n");
fwrite($stream, "0\r\n\r\n");
rewind($stream);
$this->assertEquals('hello', stream_get_contents($stream));
fclose($stream);
}
public function testAppendThrows()
{
$this->createErrorHandler($errors);
$stream = $this->createStream();
$this->createErrorHandler($errors);
StreamFilter\append($stream, function ($chunk) {
throw new \DomainException($chunk);
});
fwrite($stream, 'test');
$this->removeErrorHandler();
$this->assertCount(1, $errors);
$this->assertContains('test', $errors[0]);
}
public function testAppendThrowsDuringEnd()
{
$stream = $this->createStream();
$this->createErrorHandler($errors);
StreamFilter\append($stream, function ($chunk = null) {
if ($chunk === null) {
throw new \DomainException('end');
}
return $chunk;
});
fclose($stream);
$this->removeErrorHandler();
// We can only assert we're not seeing an exception here…
// * php 5.3-5.6 sees one error here
// * php 7 does not see any error here
// * hhvm sees the same error twice
//
// If you're curious:
//
// var_dump($errors);
// $this->assertCount(1, $errors);
// $this->assertContains('end', $errors[0]);
}
public function testAppendThrowsShouldTriggerEnd()
{
$stream = $this->createStream();
$this->createErrorHandler($errors);
$ended = false;
StreamFilter\append($stream, function ($chunk = null) use (&$ended) {
if ($chunk === null) {
$ended = true;
return '';
}
throw new \DomainException($chunk);
});
$this->assertEquals(false, $ended);
fwrite($stream, 'test');
$this->assertEquals(true, $ended);
$this->removeErrorHandler();
$this->assertCount(1, $errors);
$this->assertContains('test', $errors[0]);
}
public function testAppendThrowsShouldTriggerEndButIgnoreExceptionDuringEnd()
{
//$this->markTestIncomplete();
$stream = $this->createStream();
$this->createErrorHandler($errors);
StreamFilter\append($stream, function ($chunk = null) {
if ($chunk === null) {
$chunk = 'end';
//return '';
}
throw new \DomainException($chunk);
});
fwrite($stream, 'test');
$this->removeErrorHandler();
$this->assertCount(1, $errors);
$this->assertContains('test', $errors[0]);
}
/**
* @expectedException RuntimeException
*/
public function testAppendInvalidStreamIsRuntimeError()
{
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid stream)');
StreamFilter\append(false, function () { });
}
/**
* @expectedException RuntimeException
*/
public function testPrependInvalidStreamIsRuntimeError()
{
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid stream)');
StreamFilter\prepend(false, function () { });
}
/**
* @expectedException RuntimeException
*/
public function testRemoveInvalidFilterIsRuntimeError()
{
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (does not reject invalid filters)');
StreamFilter\remove(false);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidCallbackIsInvalidArgument()
{
$stream = $this->createStream();
StreamFilter\append($stream, 'a-b-c');
}
private function createStream()
{
return fopen('php://memory', 'r+');
}
private function createErrorHandler(&$errors)
{
$errors = array();
set_error_handler(function ($_, $message) use (&$errors) {
$errors []= $message;
});
}
private function removeErrorHandler()
{
restore_error_handler();
}
}
@@ -0,0 +1,44 @@
<?php
use Clue\StreamFilter as Filter;
class FunTest extends PHPUnit_Framework_TestCase
{
public function testFunInRot13()
{
$rot = Filter\fun('string.rot13');
$this->assertEquals('grfg', $rot('test'));
$this->assertEquals('test', $rot($rot('test')));
$this->assertEquals(null, $rot());
}
public function testFunInQuotedPrintable()
{
$encode = Filter\fun('convert.quoted-printable-encode');
$decode = Filter\fun('convert.quoted-printable-decode');
$this->assertEquals('t=C3=A4st', $encode('täst'));
$this->assertEquals('täst', $decode($encode('täst')));
$this->assertEquals(null, $encode());
}
/**
* @expectedException RuntimeException
*/
public function testFunWriteAfterCloseRot13()
{
$rot = Filter\fun('string.rot13');
$this->assertEquals(null, $rot());
$rot('test');
}
/**
* @expectedException RuntimeException
*/
public function testFunInvalid()
{
Filter\fun('unknown');
}
}
@@ -0,0 +1,79 @@
<?php
use Clue\StreamFilter;
class BuiltInZlibTest extends PHPUnit_Framework_TestCase
{
public function testFunZlibDeflateHelloWorld()
{
$deflate = StreamFilter\fun('zlib.deflate');
$data = $deflate('hello') . $deflate(' ') . $deflate('world') . $deflate();
$this->assertEquals(gzdeflate('hello world'), $data);
}
public function testFunZlibDeflateEmpty()
{
if (PHP_VERSION >= 7) $this->markTestSkipped('Not supported on PHP7 (empty string does not invoke filter)');
$deflate = StreamFilter\fun('zlib.deflate');
//$data = gzdeflate('');
$data = $deflate();
$this->assertEquals("\x03\x00", $data);
}
public function testFunZlibDeflateBig()
{
$deflate = StreamFilter\fun('zlib.deflate');
$n = 1000;
$expected = str_repeat('hello', $n);
$bytes = '';
for ($i = 0; $i < $n; ++$i) {
$bytes .= $deflate('hello');
}
$bytes .= $deflate();
$this->assertEquals($expected, gzinflate($bytes));
}
public function testFunZlibInflateHelloWorld()
{
$inflate = StreamFilter\fun('zlib.inflate');
$data = $inflate(gzdeflate('hello world')) . $inflate();
$this->assertEquals('hello world', $data);
}
public function testFunZlibInflateEmpty()
{
$inflate = StreamFilter\fun('zlib.inflate');
$data = $inflate("\x03\x00") . $inflate();
$this->assertEquals('', $data);
}
public function testFunZlibInflateBig()
{
if (defined('HHVM_VERSION')) $this->markTestSkipped('Not supported on HHVM (final chunk will not be emitted)');
$inflate = StreamFilter\fun('zlib.inflate');
$expected = str_repeat('hello', 10);
$bytes = gzdeflate($expected);
$ret = '';
foreach (str_split($bytes, 2) as $chunk) {
$ret .= $inflate($chunk);
}
$ret .= $inflate();
$this->assertEquals($expected, $ret);
}
}
@@ -17,6 +17,7 @@ return array(
'Locale' => $vendorDir . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/Locale.php',
'NumberFormatter' => $vendorDir . '/symfony/symfony/src/Symfony/Component/Intl/Resources/stubs/NumberFormatter.php',
'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php',
'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php',
'SqlFormatter' => $vendorDir . '/jdorn/sql-formatter/lib/SqlFormatter.php',
'TypeError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/TypeError.php',
);
+7 -2
View File
@@ -6,15 +6,20 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'3a37ebac017bc098e9a86b35401e7a68' => $vendorDir . '/mongodb/mongodb/src/functions.php',
'06dd8487319ccd8403765f5b8c9f2d61' => $vendorDir . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
'92c8763cd6170fce6fcfe7e26b4e8c10' => $vendorDir . '/symfony/phpunit-bridge/bootstrap.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'ddc0a4d7e61c0286f0f8593b1903e894' => $vendorDir . '/clue/stream-filter/src/functions.php',
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'6a47392539ca2329373e0d33e1dba053' => $vendorDir . '/symfony/polyfill-intl-icu/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
'3a37ebac017bc098e9a86b35401e7a68' => $vendorDir . '/mongodb/mongodb/src/functions.php',
'ce89ac35a6c330c55f4710717db9ff78' => $vendorDir . '/kriswallsmith/assetic/src/functions.php',
'06dd8487319ccd8403765f5b8c9f2d61' => $vendorDir . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
);

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