Trinity updates

This commit is contained in:
Simon Vieille 2016-06-20 11:37:14 +02:00
parent 3869dc0293
commit afa84408fb
71 changed files with 2083 additions and 983 deletions

Binary file not shown.

View file

@ -135,3 +135,8 @@ trinity:
title: 'New'
edit:
title: "Edition"
akamai:
akamaiadmin:
index:
title: "Akamai purge request"

View file

@ -135,3 +135,8 @@ trinity:
title: "Nouveau"
edit:
title: "Édition"
akamai:
akamaiadmin:
index:
title: "Akamai purge request"

View file

@ -770,7 +770,7 @@ class BaseAdminController extends Controller
}
/**
* @Route("/jsTranslations.js", name="TrinityAdminBundle_jsTranslation")
* @Route("/admin/jsTranslations", name="TrinityAdminBundle_jsTranslation")
* @Template("TrinityAdminBundle:BaseAdmin:jsTranslation.html.twig")
*/
public function jsTranslationAction(Request $request)

View file

@ -29,20 +29,44 @@
{% if '*' in fieldsets[key] %}
<div class="control-group well">
{% for fieldname, field in form %}
{% if fieldsnames %}
{% set label = fieldsnames[fieldname] is defined ? fieldsnames[fieldname] : fieldname %}
{% else %}
{% set label = fieldname %}
{% endif %}
{% if not field.isRendered() %}
{% if fieldsnames %}
{% set label = fieldsnames[fieldname] is defined ? fieldsnames[fieldname] : fieldname %}
{% else %}
{% set label = fieldname %}
{% endif %}
{% if 'hidden' not in field.vars.block_prefixes %}
{{ form_label(form[fieldname], null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
{% if 'hidden' not in field.vars.block_prefixes %}
{{ form_label(form[fieldname], null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
<div class="controls clearfix">
{{ form_errors(form[fieldname]) }}
{{ form_widget(form[fieldname]) }}
</div>
<div class="controls clearfix">
{{ form_errors(form[fieldname]) }}
{{ form_widget(form[fieldname]) }}
</div>
{% endif %}
{% endfor %}
</div>
{% elseif fieldsets[key]['matches'] is defined %}
{% set regex_match = '/' ~ fieldsets[key]['matches'] ~ '/' %}
<div class="control-group well">
{% for fieldname, field in form %}
{% if not field.isRendered() and fieldname matches regex_match %}
{% if fieldsnames %}
{% set label = fieldsnames[fieldname] is defined ? fieldsnames[fieldname] : fieldname %}
{% else %}
{% set label = fieldname %}
{% endif %}
{% if 'hidden' not in field.vars.block_prefixes %}
{{ form_label(form[fieldname], null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
<div class="controls clearfix">
{{ form_errors(form[fieldname]) }}
{{ form_widget(form[fieldname]) }}
</div>
{% endif %}
{% endfor %}
</div>
{% else %}

View file

@ -0,0 +1,57 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Configuration;
class AkamaiCrudConfiguration extends \Trinity\Bundle\AdminBundle\Configuration\CrudConfiguration
{
public function __construct()
{
$this
->setModelNamespace('Trinity\\Bundle\\AkamaiBundle\\Model')
->setModel('AkamaiEvent')
->setModelPeer('AkamaiEventPeer')
->setModelQuery('AkamaiEventQuery')
->setRoutePrefix('TrinityAkamaiBundleAkamaiAdmin')
->setFormNamespace('Trinity\\Bundle\\AkamaiBundle\\Form\Type')
->setFormEdit('AkamaiEventType')
->setFormFilter('AkamaiEventFilterType')
->setFormNew('AkamaiEventType')
->setFieldsets(array(
'' => array(
'*',
),
))
->setMaxPerPage(100)
->setRankable(false)
->setListTitle('Akamai purge requests')
->setNewTitle('New AkamaiEvent Akamai')
->setEditTitle('Edition of "%reference%"')
->setBatchActions(array())
->removeIndexAction('new')
->removeIndexListAction('edit')
->removeIndexListAction('delete')
->removeIndexListAction('remove')
// ->setDisplayFields(array(
// 'reference',
// 'description',
// ))
// Listing:
// ->setFieldTemplate('visible', 'TrinityAdminBundle:BaseAdmin:bool.html.twig')
// ->setDisplayFields(array(
//
// ))
// ->setFieldname('foo', 'bar')
;
}
}

View file

@ -0,0 +1,93 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Trinity\Bundle\AdminBundle\Controller\BaseAdminController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Trinity\Bundle\AkamaiBundle\Configuration\AkamaiCrudConfiguration as CrudConfiguration;
/**
* @Route("/admin/akamai")
*/
class AkamaiAdminController extends BaseAdminController
{
public function __construct()
{
$this->configuration = new CrudConfiguration();
}
/**
* @Route("/{page}", name="TrinityAkamaiBundleAkamaiAdmin_index", defaults={"page" = "1"}, requirements={"page" = "\d+"})
* @Template()
*/
public function indexAction($page, Request $request)
{
return parent::indexAction($page, $request);
}
/**
* @Route("/new", name="TrinityAkamaiBundleAkamaiAdmin_new")
* @Template()
*/
public function newAction(Request $request)
{
return parent::newAction($request);
}
/**
* @Route("/edit/{id}", name="TrinityAkamaiBundleAkamaiAdmin_edit")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NotificationBundle\Model\Template")
*/
public function editAction($object, Request $request)
{
return parent::editAction($object, $request);
}
/**
* @Route("/remove/{id}/{token}", name="TrinityAkamaiBundleAkamaiAdmin_remove")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NotificationBundle\Model\Template")
*/
public function removeAction($object, $token, Request $request)
{
return parent::removeAction($object, $token, $request);
}
/**
* @Route("/batch", name="TrinityAkamaiBundleAkamaiAdmin_batch")
* @Template()
* @Method({"POST"})
*/
public function batchAction(Request $request)
{
return parent::batchAction($request);
}
/**
* @Route("/filter/clear", name="TrinityAkamaiBundleAkamaiAdmin_filter_clear")
* @Template()
*/
public function clearFilterAction(Request $request)
{
return parent::clearFilterAction($request);
}
/**
* @Route("/rank", name="TrinityAkamaiBundleAkamaiAdmin_rank")
* @Template("TrinityAdminBundle:BaseAdmin:rank.html.twig")
* @Method({"POST"})
*/
public function rankAction(Request $request)
{
return parent::rankAction($request);
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('trinity_akamai');
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
$rootNode->children()->scalarNode('base_url')->isRequired()->end();
return $treeBuilder;
}
}

View file

@ -0,0 +1,30 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class TrinityAkamaiExtension extends Extension
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('akamai', $config);
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class AkamaiEvent extends Event
{
private $url = null;
private $object = null;
/**
* @return mixed
*/
public function getUrl()
{
return $this->url;
}
/**
* @param mixed $url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* @return mixed
*/
public function getObject()
{
return $this->object;
}
/**
* @param mixed $object
*/
public function setObject($object)
{
$this->object = $object;
}
public function getObjectClass()
{
if($this->object === null){
return null;
}
return get_class($this->object);
}
public function getObjectId()
{
if($this->object === null){
return null;
}
return $this->object->getId();
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\EventListener;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Trinity\Bundle\AkamaiBundle\Event\AkamaiEvent;
use Trinity\Bundle\AkamaiBundle\TrinityAkamaiEvents;
class AkamaiSubscriber implements EventSubscriberInterface
{
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public static function getSubscribedEvents()
{
return array(
TrinityAkamaiEvents::AKAMAI_PURGE => 'purge',
);
}
public function purge(AkamaiEvent $event)
{
$urls = $event->getUrl();
if(is_array($urls)){
$data = ['objects' => $urls];
} else {
$data = ['objects' => [$urls]];
}
// $response = $this->container->get('trinity.akamai.ccu.client')->addRequest($data);
//
// $record = new \Trinity\Bundle\AkamaiBundle\Model\AkamaiEvent();
// $record
// ->setRawData(serialize($data))
// ->setRawResponse(serialize($response))
// ->setObjectClass($event->getObjectClass())
// ->setObjectId($event->getObjectId())
// ->setProgressUri(isset($response['progressUri']) ? $response['progressUri'] : null)
// ->setPurgeId(isset($response['purgeId']) ? $response['purgeId'] : null)
// ->setSupportId(isset($response['supportId']) ? $response['supportId'] : null)
// ->save();
}
}

View file

@ -0,0 +1,38 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Form\Type;
use Propel\PropelBundle\Form\BaseAbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class AkamaiEventFilterType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'Trinity\Bundle\AkamaiBundle\Model\AkamaiEvent',
'name' => 'event',
'csrf_protection' => false,
);
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'purge_id',
'text',
array(
'required' => false,
)
);
$builder->add(
'support_id',
'text',
array(
'required' => false,
)
);
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Form\Type;
use Propel\PropelBundle\Form\BaseAbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;
class AkamaiEventType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'Trinity\Bundle\AkamaiBundle\Model\AkamaiEvent',
'name' => 'event',
);
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
}
}

View file

@ -0,0 +1,9 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Model;
use Trinity\Bundle\AkamaiBundle\Model\om\BaseAkamaiEvent;
class AkamaiEvent extends BaseAkamaiEvent
{
}

View file

@ -0,0 +1,9 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Model;
use Trinity\Bundle\AkamaiBundle\Model\om\BaseAkamaiEventPeer;
class AkamaiEventPeer extends BaseAkamaiEventPeer
{
}

View file

@ -0,0 +1,9 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Model;
use Trinity\Bundle\AkamaiBundle\Model\om\BaseAkamaiEventQuery;
class AkamaiEventQuery extends BaseAkamaiEventQuery
{
}

View file

@ -0,0 +1,3 @@
Le bundle nécessite l'installation du bundle Guzzle
Les appels au service Akamai sont réalisé au travers d'évenement.

View file

@ -0,0 +1,20 @@
<database name="default" namespace="Trinity\Bundle\AkamaiBundle\Model" defaultIdMethod="native"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xsd.propelorm.org/1.6/database.xsd">
<table name="akamai_event">
<column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true"/>
<!-- Données event -->
<column name="raw_data" type="longvarchar"/>
<!-- Données response -->
<column name="progress_uri" type="varchar" size="255"/>
<column name="purge_id" type="varchar" size="255"/>
<column name="support_id" type="varchar" size="255"/>
<column name="raw_response" type="longvarchar"/>
<!-- Données object -->
<column name="object_class" type="varchar" size="255"/>
<column name="object_id" type="INTEGER"/>
<behavior name="timestampable"/>
</table>
</database>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="trinity.akamai.ccu.client.class">Trinity\Bundle\AkamaiBundle\Service\AkamaiCcuClient</parameter>
<parameter key="trinity.akamai.listener.class">Trinity\Bundle\AkamaiBundle\EventListener\AkamaiSubscriber</parameter>
</parameters>
<services>
<service id="trinity.akamai.ccu.client" class="%trinity.akamai.ccu.client.class%">
<argument>%akamai%</argument>
</service>
<service id="trinity.akamai.listener" class="%trinity.akamai.listener.class%">
<tag name="kernel.event_subscriber"/>
<argument type="service" id="service_container"/>
</service>
</services>
</container>

View file

@ -0,0 +1 @@
{% extends "TrinityAdminBundle:BaseAdmin:edit.html.twig" %}

View file

@ -0,0 +1 @@
{% extends "TrinityAdminBundle:BaseAdmin:index.html.twig" %}

View file

@ -0,0 +1 @@
{% extends "TrinityAdminBundle:BaseAdmin:new.html.twig" %}

View file

@ -0,0 +1,126 @@
<?php
namespace Trinity\Bundle\AkamaiBundle\Service;
use Guzzle\Common\Exception\GuzzleException;
use Guzzle\Http\Exception\HttpException;
use Guzzle\Http\Exception\RequestException;
use GuzzleHttp\Client;
use GuzzleHttp\Command\Guzzle\Description;
use GuzzleHttp\Command\Guzzle\GuzzleClient;
use GuzzleHttp\Exception\ClientException;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Class AkamaiCcuApi
* @package Trinity\Bundle\AkamaiBundle\Service
* @require Guzzle
*/
class AkamaiCcuClient extends GuzzleClient
{
public function __construct(array $akamai_ws = [], array $config = [])
{
$resolver = new OptionsResolver();
$this->configureOptionResolver($resolver);
// validation des paramètres
$options = $resolver->resolve($akamai_ws);
// initialisation du client standard Guzzle
$client = new Client([
"defaults" => [
// headers attendus
"headers" => [
"Content-Type" => "application/json",
"Accept" => "application/json",
],
],
"base_url" => $options["base_url"]
]);
// définition des requètes supportées par notre service
$description = new Description([
"name" => 'Akamai',
"description" => "Content Control Utility",
"operations" => [
"getQueue" => [
"httpMethod" => "GET",
"uri" => "/ccu/v2/queues/{queueName}",
"responseModel" => "jsonResponse",
"parameters" => [
"queueName" => [
'type' => 'string',
'default' => 'default',
'location' => 'uri'
],
],
],
"addRequest" => [
"httpMethod" => "POST",
"uri" => "/ccu/v2/queues/{queueName}",
"responseModel" => "jsonResponse",
"parameters" => [
"queueName" => [
'type' => 'string',
'default' => 'default',
'location' => 'uri'
],
"objects" => [
'type' => 'array',
'required' => true,
'location' => 'postField'
],
"action" => [
'type' => 'string',
'default' => 'remove',
'location' => 'postField'
],
"type" => [
'type' => 'string',
'default' => 'url',
'location' => 'postField'
],
"domain" => [
'type' => 'string',
'default' => 'production',
'location' => 'postField'
]
]
],
"getStatus" => [
"httpMethod" => "GET",
"uri" => "/ccu/v2/purges/{purgeId}",
"responseModel" => "jsonResponse",
"parameters" => [
"purgeId" => [
'type' => 'string',
'required' => true,
'location' => 'uri'
]
],
],
],
// les models permettent de définir le traitement appliqué aux réponses de l'API
// on spécifie ici que l'on veut un objet php à partir du json contenu dans la réponse
"models" => [
"jsonResponse" => [
"type" => "object",
"additionalProperties" => [
"location" => "json"
]
]
]
]);
parent::__construct($client, $description, $config);
}
protected function configureOptionResolver(OptionsResolverInterface $resolver)
{
$resolver
->setRequired([
'base_url',
]);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Trinity\Bundle\AkamaiBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class TrinityAkamaiBundle extends Bundle
{
}

View file

@ -0,0 +1,11 @@
<?php
namespace Trinity\Bundle\AkamaiBundle;
final class TrinityAkamaiEvents
{
/**
* Demande de request post pour purger le cache Akamai
*/
const AKAMAI_PURGE = 'trinity.akamai.purge';
}

View file

@ -7,6 +7,8 @@ use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Trinity\Bundle\AkamaiBundle\Event\AkamaiEvent;
use Trinity\Bundle\AkamaiBundle\TrinityAkamaiEvents;
use Trinity\Bundle\ContentManagerBundle\Model\MenuPeer;
use Trinity\Bundle\ContentManagerBundle\Model\NavQuery;
use Trinity\Bundle\ContentManagerBundle\Form\Type\PageMetasType;
@ -83,21 +85,31 @@ class PageAdminController extends BaseAdminController
*/
public function removeAction($object, $token, Request $request)
{
$this->use_nav_name = $this->container->getParameter('trinity_content_manager.index_use_nav_name');
if ($object->getNodeRelatedByNodeId() !== null) {
$event = new LuceneEvent();
/** @var $object Page */
if($this->isBundleEnabled('TrinityAkamaiBundle') && $object->getNode()){
$event = new AkamaiEvent();
$event->setUrl($this->generateUrl($object->getNode()->getRealRouteName()));
$event->setObject($object);
$nav = $object->getNodeRelatedByNodeId()->getNav();
if($this->use_nav_name){
$event->setIndex($nav->getName());
}else {
$event->setIndex($nav->getCulture());
}
$this->get('event_dispatcher')->dispatch(TrinityAkamaiEvents::AKAMAI_PURGE, $event);
}
$this->get("event_dispatcher")->dispatch(
TrinitySearchEvents::LUCENE_REMOVE_INDEX, $event
);
if ($this->isBundleEnabled('TrinitySearchBundle')) {
$this->use_nav_name = $this->container->getParameter('trinity_content_manager.index_use_nav_name');
if ($object->getNodeRelatedByNodeId() !== null) {
$event = new LuceneEvent();
$event->setObject($object);
$nav = $object->getNodeRelatedByNodeId()->getNav();
if ($this->use_nav_name) {
$event->setIndex($nav->getName());
} else {
$event->setIndex($nav->getCulture());
}
$this->get("event_dispatcher")->dispatch(
TrinitySearchEvents::LUCENE_REMOVE_INDEX, $event
);
}
}
return parent::removeAction($object, $token, $request);
@ -430,23 +442,44 @@ class PageAdminController extends BaseAdminController
public function postSave($object, $was_new = false)
{
$this->use_nav_name = $this->container->getParameter('trinity_content_manager.index_use_nav_name');
$node = $object->getNodeRelatedByNodeId();
if ($node) {
$event = new LuceneEvent();
/** @var $object Page */
if($this->isBundleEnabled('TrinityAkamaiBundle') && !$was_new && $object->getNode()){
$event = new AkamaiEvent();
$event->setUrl($this->generateUrl($object->getNode()->getRealRouteName(),array('_locale' => $object->getNode()->getNav()->getLocale()),true));
$event->setObject($object);
$nav = $node->getNav();
if($this->use_nav_name){
$event->setIndex($nav->getName());
}else {
$event->setIndex($nav->getCulture());
}
$this->get('event_dispatcher')->dispatch(TrinityAkamaiEvents::AKAMAI_PURGE, $event);
}
$this->get("event_dispatcher")->dispatch(
TrinitySearchEvents::LUCENE_UPDATE_INDEX, $event
);
if($this->isBundleEnabled('TrinitySearchBundle')){
$this->use_nav_name = $this->container->getParameter('trinity_content_manager.index_use_nav_name');
$node = $object->getNodeRelatedByNodeId();
if ($node) {
$event = new LuceneEvent();
$event->setObject($object);
$nav = $node->getNav();
if($this->use_nav_name){
$event->setIndex($nav->getName());
}else {
$event->setIndex($nav->getCulture());
}
$this->get("event_dispatcher")->dispatch(
TrinitySearchEvents::LUCENE_UPDATE_INDEX, $event
);
}
}
}
protected function isBundleEnabled($bundle)
{
$bundles = array_keys($this->container->get('kernel')->getBundles());
if (in_array($bundle, $bundles)) {
return true;
}
return false;
}
}

View file

@ -621,6 +621,10 @@ class Node extends BaseNode
{
$default = array('value' => array());
if ($this->getNav() && $this->getNav()->getLocale()) {
$default['value']['_locale'] = $this->getNav()->getLocale();
}
try {
$value = $this->parser->parse($this->getDefaultParams());

View file

@ -1,37 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Configuration;
class ModelCrudConfiguration extends \Trinity\Bundle\AdminBundle\Configuration\CrudConfiguration
{
public function __construct() {
$this
->setModelNamespace('Trinity\\Bundle\\NewsletterBundle\\Model')
->setModel('Model')
->setModelPeer('ModelPeer')
->setModelQuery('ModelQuery')
->setRoutePrefix('TrinityNewsletterBundleModelAdmin')
->setFormNamespace('Trinity\\Bundle\\NewsletterBundle\\Form\\Type')
->setFormEdit('ModelType')
->setFormFilter('ModelFilterType')
->setFormNew('ModelType')
->setDisplayFields(array('name','class_key','template','updated_at','created_at'))
->setListTitle('Available newsletter models')
->setFieldTemplate('class_key','TrinityNewsletterBundle:ModelAdmin:class_key.html.twig')
->setFieldTemplate('template','TrinityNewsletterBundle:ModelAdmin:template.html.twig')
->setNewTitle('New newsletter model')
->setEditTitle('Edit newsletter model "%name%"')
->setFieldHelper('classKey','You must save a type of model to edit it\'s content')
->setFieldsets(array(
'Configuration' => array('name','classKey','template'),
'Content' => array('*')
))
->setMaxPerPage(20)
;
}
}

View file

@ -4,37 +4,60 @@ namespace Trinity\Bundle\NewsletterBundle\Configuration;
class NewsletterCrudConfiguration extends \Trinity\Bundle\AdminBundle\Configuration\CrudConfiguration
{
public function __construct() {
public function __construct()
{
$this
->setModelNamespace('Trinity\\Bundle\\NewsletterBundle\\Model')
->setModel('Newsletter')
->setModelPeer('NewsletterPeer')
->setModelQuery('NewsletterQuery')
->setModelNamespace('Trinity\\Bundle\\NewsletterBundle\\Model')
->setModel('Newsletter')
->setModelPeer('NewsletterPeer')
->setModelQuery('NewsletterQuery')
->setRoutePrefix('TrinityNewsletterBundleNewsletterAdmin')
->setRoutePrefix('TrinityNewsletterBundleNewsletterAdmin')
->setFormNamespace('Trinity\\Bundle\\NewsletterBundle\\Form\\Type')
->setFormEdit('NewsletterType')
->setFormFilter('NewsletterFilterType')
->setFormNew('NewsletterType')
->setFormNamespace('Trinity\\Bundle\\NewsletterBundle\\Form\\Type')
->setFormEdit('trinity.newsletter.form.newsletter_type', false)
->setFormNew('trinity.newsletter.form.newsletter_type', false)
->setFormFilter('NewsletterFilterType')
->setDisplayFields(array('id','name','sender_name','model','sentAt','created_at'))
->setListTitle('Newsletters')
->setFilterMethod('sentAt','filterBySentAt',\Criteria::GREATER_EQUAL)
->setDisplayFields(array('id', 'name', 'class_key', 'recipients_groups', 'stats', 'sentAt'))
->setNewTitle('Create a newsletter')
->setEditTitle('Edit newsletter "%name%"')
->setFieldsets(array(
'' => array('name'),
'Configuration' => array('senderName','senderEmail','model'),
'Recipients' => array('emailListing','groups'),
))
->setListTitle('Newsletters')
->setIndexListAction('send','TrinityNewsletterBundle:NewsletterAdmin:listSend.html.twig')
->setIndexListAction('preview','TrinityNewsletterBundle:NewsletterAdmin:listPreview.html.twig')
->setFilterMethod('sentAt', 'filterBySentAt', \Criteria::GREATER_EQUAL)
->setMaxPerPage(20)
;
->setNewTitle('Create a newsletter')
->setEditTitle('Edit newsletter "%name%"')
->setFieldsets(array(
'Configuration' => array('name', 'senderName', 'senderEmail', 'classKey', 'template'),
'Recipients' => array('emailListing', 'groups', 'emailFile', 'emailFileVar'),
'Content' => array('matches' => 'block_*'),
// 'Compléments' => array('*')
))
->setFieldsetsView('tab')
->setRedirectIfOneResult(false)
->setFieldTemplate('class_key', 'TrinityNewsletterBundle:NewsletterAdmin:class_key.html.twig')
->setFieldTemplate('template', 'TrinityNewsletterBundle:NewsletterAdmin:template.html.twig')
->setFieldTemplate('recipients_groups', 'TrinityNewsletterBundle:NewsletterAdmin:recipients_groups.html.twig')
->setFieldTemplate('stats', 'TrinityNewsletterBundle:NewsletterAdmin:stats.html.twig')
->setIndexListActions(
array(
'preview' => 'TrinityNewsletterBundle:NewsletterAdmin:listPreview.html.twig',
'edit' => 'TrinityAdminBundle:BaseAdmin:listEdit.html.twig',
'remove' => 'TrinityAdminBundle:BaseAdmin:listRemove.html.twig',
'send' => 'TrinityNewsletterBundle:NewsletterAdmin:listSend.html.twig',
)
)
->setFieldname('Id','ID')
->setFieldname('name','Nom')
->setFieldname('class_key','Modèle')
->setFieldname('template','Mise en forme')
->setFieldname('recipients_groups','Groupes destinataires')
->setFieldname('stats','Statistiques')
->setFieldname('sentAt','Envoyé le')
->setMaxPerPage(40);
}
}

View file

@ -1,160 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Trinity\Bundle\NewsletterBundle\Configuration\ModelCrudConfiguration as CrudConfiguration;
use Trinity\Bundle\AdminBundle\Controller\BaseAdminController;
use Trinity\Bundle\UserBundle\Flash\FlashError;
use Trinity\Bundle\UserBundle\Flash\FlashSuccess;
use Trinity\Bundle\UserBundle\Flash\FlashWarning;
/**
* @Route("/admin/newsletter/model")
*/
class ModelAdminController extends BaseAdminController
{
public function __construct()
{
$this->configuration = new CrudConfiguration();
}
/**
* @Route("/list/{page}", name="TrinityNewsletterBundleModelAdmin_index", defaults={"page" = "1"}, requirements={"page" = "\d+"})
* @Template()
*/
public function indexAction($page, Request $request)
{
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$templates = array();
foreach($options['models'] as $key => $model)
{
$templates[$key] = array();
foreach($model['templates'] as $template){
$templates[$key][$template['template']] = $template['title'];
}
}
return array_merge(
parent::indexAction($page, $request),
array(
'models' => $options['models'],
'templates' => $templates
)
);
}
/**
* @Route("/new", name="TrinityNewsletterBundleModelAdmin_new")
* @Template()
*/
public function newAction(Request $request)
{
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$model = $this->getConfiguration()->getModel();
$object = new $model();
$form = $this->getConfiguration()->getFormNew();
$form = $this->createForm(new $form($options), $object);
if ('POST' === $request->getMethod()) {
if (false !== $processForm = $this->processForm($form, $object, $request)) {
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.updated.singular'), false, $this->getConfiguration()->getStorageNamespace());
return $processForm;
}
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.new'), false, $this->getConfiguration()->getStorageNamespace());
}
return array(
'form' => $form->createView(),
'fieldsets' => $this->getConfiguration()->getFieldsets(),
'fieldsnames' => $this->getConfiguration()->getFieldsnames(),
'fields_helpers' => $this->getConfiguration()->getFieldsHelpers(),
'title' => $this->getConfiguration()->getNewTitle(),
'i18n' => $this->getConfiguration()->getI18n(),
'i18n_cultures' => $this->getConfiguration()->getI18nCultures(),
);
}
/**
* @Route("/edit/{id}", name="TrinityNewsletterBundleModelAdmin_edit")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NewsletterBundle\Model\Model")
*/
public function editAction($object, Request $request)
{
if (!$object) {
$this->getSessionUser()->setFlash('message', new FlashWarning('crud.flash.unknown'), false, $this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl(sprintf('%s_index',$this->getConfiguration()->getRoutePrefix())));
}
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$form = $this->getConfiguration()->getFormEdit();
$form = $this->createForm(new $form($options), $object);
if ('POST' === $request->getMethod()) {
if (false !== $processForm = $this->processForm($form, $object, $request)) {
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.updated.singular'), false, $this->getConfiguration()->getStorageNamespace());
return $processForm;
}
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.update'), false, $this->getConfiguration()->getStorageNamespace());
}
return array(
'object' => $object,
'form' => $form->createView(),
'fieldsets' => $this->getConfiguration()->getFieldsets(),
'fieldsnames' => $this->getConfiguration()->getFieldsnames(),
'fields_helpers' => $this->getConfiguration()->getFieldsHelpers(),
'remove_token' => $this->getRemoveToken(true),
'title' => $this->getConfiguration()->getEditTitle($object),
'i18n' => $this->getConfiguration()->getI18n(),
'i18n_cultures' => $this->getConfiguration()->getI18nCultures(),
);
}
/**
* @Route("/remove/{id}/{token}", name="TrinityNewsletterBundleModelAdmin_remove")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NewsletterBundle\Model\Model")
*/
public function removeAction($object, $token, Request $request)
{
return parent::removeAction($object, $token, $request);
}
/**
* @Route("/batch", name="TrinityNewsletterBundleModelAdmin_batch")
* @Template()
* @Method({"POST"})
*/
public function batchAction(Request $request)
{
return parent::batchAction($request);
}
/**
* @Route("/filter/clear", name="TrinityNewsletterBundleModelAdmin_filter_clear")
* @Template()
*/
public function clearFilterAction(Request $request)
{
return parent::clearFilterAction($request);
}
}

View file

@ -7,14 +7,20 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Trinity\Bundle\NewsletterBundle\Configuration\NewsletterCrudConfiguration as CrudConfiguration;
use Symfony\Component\HttpFoundation\Request;
use Trinity\Bundle\AdminBundle\Controller\BaseAdminController;
use Trinity\Bundle\NewsletterBundle\Model\Newsletter;
use Trinity\Bundle\NewsletterBundle\Model\NewsletterQuery;
use Trinity\Bundle\UserBundle\Flash\FlashError;
use Trinity\Bundle\UserBundle\Flash\FlashSuccess;
use \FOS\UserBundle\Propel\UserQuery;
use \FOS\UserBundle\Propel\GroupQuery;
use Trinity\Bundle\UserBundle\Flash\FlashWarning;
use WD\Component\Csv\CsvParser;
/**
* @Route("/admin/newsletter")
@ -26,13 +32,51 @@ class NewsletterAdminController extends BaseAdminController
$this->configuration = new CrudConfiguration();
}
protected function getFormFilter($new = false)
{
$form = $this->getConfiguration()->getFormFilter() ? $this->getConfiguration()->getFormFilter() : $this->getConfiguration()->getFormNew();
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$options = array_merge(
$this->getConfiguration()->getFormFilterOptions(),
array('models' => $options['models'])
);
$form = $this->createForm(new $form($options));
if (!$new) {
$datas = $this->cleanFilterArray($this->getSessionUser()->getAttribute('filter', array(),
$this->getConfiguration()->getStorageNamespace()));
$form->bind($datas);
}
return $form;
}
/**
* @Route("/list/{page}", name="TrinityNewsletterBundleNewsletterAdmin_index", defaults={"page" = "1"}, requirements={"page" = "\d+"})
* @Template()
*/
public function indexAction($page, Request $request)
{
return parent::indexAction($page, $request);
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$templates = array();
foreach ($options['models'] as $key => $model) {
$templates[$key] = array();
foreach ($model['templates'] as $template) {
$templates[$key][$template['template']] = $template['title'];
}
}
return array_merge(
parent::indexAction($page, $request),
array(
'models' => $options['models'],
'templates' => $templates
)
);
}
/**
@ -41,7 +85,58 @@ class NewsletterAdminController extends BaseAdminController
*/
public function newAction(Request $request)
{
return parent::newAction($request);
$options = $this->getConfiguration()->getFormNewOptions();
if ($this->has('global_vars')) {
$sender_name = $this->get('global_vars')->get('trinity_newsletter_sender_name');
$sender_mail = $this->get('global_vars')->get('trinity_newsletter_sender_mail');
$this->getConfiguration()->setFormNewOptions(
array_merge(
$options,
array(
'sender_name' => $sender_name,
'sender_mail' => $sender_mail
)
)
);
}
$options = $this->getConfiguration()->getFormNewOptions();
$options_nws = $this->container->getParameter('trinity_newsletter.newsletter');
$options = array_merge($options, $options_nws);
$model = $this->getConfiguration()->getModel();
$object = new $model();
$form = $this->getConfiguration()->getFormNew();
if ($this->has($form)) {
$form = $this->createForm($this->get($form)->getName(), $object, $options);
} else {
$form = $this->createForm(new $form($options), $object);
}
if ('POST' === $request->getMethod()) {
if (false !== $processForm = $this->processForm($form, $object, $request)) {
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.updated.singular'), false,
$this->getConfiguration()->getStorageNamespace());
return $processForm;
}
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.new'), false,
$this->getConfiguration()->getStorageNamespace());
}
return array(
'form' => $form->createView(),
'fieldsets' => $this->getConfiguration()->getFieldsets(),
'fieldsetsView' => $this->getConfiguration()->getFieldsetsView(),
'fieldsnames' => $this->getConfiguration()->getFieldsnames(),
'fields_helpers' => $this->getConfiguration()->getFieldsHelpers(),
'title' => $this->getConfiguration()->getNewTitle(),
'i18n' => $this->getConfiguration()->getI18n(),
'i18n_cultures' => $this->getConfiguration()->getI18nCultures(),
'collections' => $this->getConfiguration()->getCollections(),
);
}
/**
@ -51,7 +146,50 @@ class NewsletterAdminController extends BaseAdminController
*/
public function editAction($object, Request $request)
{
return parent::editAction($object, $request);
if (!$object) {
$this->getSessionUser()->setFlash('message', new FlashWarning('crud.flash.unknown'), false,
$this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl(sprintf('%s_index',
$this->getConfiguration()->getRoutePrefix())));
}
$options = $this->container->getParameter('trinity_newsletter.newsletter');
$form = $this->getConfiguration()->getFormEdit();
if ($this->has($form)) {
$form = $this->createForm($this->get($form)->getName(), $object, $options);
} else {
$form = $this->createForm(new $form($options), $object);
}
if ('POST' === $request->getMethod()) {
if (false !== $processForm = $this->processForm($form, $object, $request)) {
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.updated.singular'), false,
$this->getConfiguration()->getStorageNamespace());
return $processForm;
}
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.update'), false,
$this->getConfiguration()->getStorageNamespace());
}
return array(
'object' => $object,
'created_at' => (method_exists($object, 'getCreatedAt')) ? $object->getCreatedAt('d/m/Y') : null,
'updated_at' => (method_exists($object, 'getUpdatedAt')) ? $object->getUpdatedAt('d/m/Y') : null,
'form' => $form->createView(),
'fieldsets' => $this->getConfiguration()->getFieldsets(),
'fieldsetsView' => $this->getConfiguration()->getFieldsetsView(),
'fieldsnames' => $this->getConfiguration()->getFieldsnames(),
'fields_helpers' => $this->getConfiguration()->getFieldsHelpers(),
'remove_token' => $this->getRemoveToken(true),
'title' => $this->getConfiguration()->getEditTitle($object),
'i18n' => $this->getConfiguration()->getI18n(),
'i18n_cultures' => $this->getConfiguration()->getI18nCultures(),
'collections' => $this->getConfiguration()->getCollections(),
);
}
/**
@ -90,60 +228,148 @@ class NewsletterAdminController extends BaseAdminController
*/
public function sendAction($object, Request $request)
{
/** @var $object Newsletter */
if ($object->getSentAt()) {
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.send'), false, $this->getConfiguration()->getStorageNamespace());
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.send'), false,
$this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl('TrinityNewsletterBundleNewsletterAdmin_index'));
}
if (!$object->getModelId()) {
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.no_model'), false, $this->getConfiguration()->getStorageNamespace());
if (!$object->getClassKey()) {
$this->getSessionUser()->setFlash('message', new FlashError('crud.flash.fail.no_model'), false,
$this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl('TrinityNewsletterBundleNewsletterAdmin_index'));
}
$object->setSentAt(new \DateTime('now'))->save();
$object->setSentAt(new \DateTime('now'));
$blocks = array();
foreach ($object->getModel()->getBlocks() as $block) {
foreach ($object->getBlocks() as $block) {
$blocks[$block->getName()] = $block;
}
$message = \Swift_Message::newInstance()
->setSubject($object->getName())
->setFrom(array($object->getSenderEmail() => $object->getSenderName()))
;
->setSubject($object->getSubject())
->setFrom(array($object->getSenderEmail() => $object->getSenderName()));
foreach ($object->getRecipients() as $email) {
$user = UserQuery::create()->filterByEmail($email)->findOne();
if ($object->getEmailFileVar() && $object->getEmailVarDesc()) {
if (!$user) {
$user = $this->generateNewsletterUser($email);
$filename = $object->getEmailFileVarAsFile()->getRealPath();
$parser = new CsvParser($filename, ';', '"', '\\', true);
$parser->parse();
$legend = $parser->getLegend();
$datas = $parser->getDatas();
$unsubscribed = $object->getUnsubscribed();
$sended = 0;
$blacklisted = 0;
foreach ($datas as $line) {
$email = trim($line[0]);
if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
continue;
}
if(in_array($email, $unsubscribed)){
$blacklisted++;
continue;
}
$token = $this->generateUnsubscribeToken($email);
$user = UserQuery::create()->filterByEmail($email)->findOne();
if ($user) {
$user->setUnsubscribeToken($token);
$user->save();
}
$body = $this->renderView(
$object->getTemplate(),
array(
'model' => $object,
'blocks' => $blocks,
'email' => $email,
'unsubscribe_token' => $token
)
);
foreach ($legend as $term) {
$token = $object->tokenize($term);
$value = $line[$term];
$body = str_replace($token, trim($value), $body);
}
$message
->setTo($email)
->setBody($body, 'text/html');
$this->get('swiftmailer.mailer.spool_mailer')->send($message);
$sended++;
}
if (!$user->getUnsubscribeToken()) {
$user->setUnsubscribeToken($this->generateUnsubscribeToken());
$user->save();
$object->setBlacklistNumber($blacklisted);
$object->setRecipientsNumber($sended);
} else {
foreach ($object->getRecipients() as $email) {
$user = UserQuery::create()->filterByEmail($email)->findOne();
$token = $this->generateUnsubscribeToken($email);
if ($user) {
$user->setUnsubscribeToken($token);
$user->save();
}
$body = $this->renderView(
$object->getTemplate(),
array(
'model' => $object,
'blocks' => $blocks,
'email' => $email,
'unsubscribe_token' => $token
)
);
$message
->setTo($email)
->setBody($body, 'text/html');
$this->get('swiftmailer.mailer.spool_mailer')->send($message);
}
$body = $this->renderView(
$object->getModel()->getTemplate(),
array(
'model' => $object->getModel(),
'blocks' => $blocks,
'user' => $user)
);
$message
->setTo($email)
->setBody($body,'text/html')
;
$this->get('mailer')->send($message);
}
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.success.send'), false, $this->getConfiguration()->getStorageNamespace());
$object->save();
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.success.send'), false,
$this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl('TrinityNewsletterBundleNewsletterAdmin_index'));
}
/**
* @Route("/copy/{id}", name="TrinityNewsletterBundleNewsletterAdmin_copy")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NewsletterBundle\Model\Newsletter")
*/
public function copyAction($object, Request $request)
{
NewsletterQuery::create()
->findPK($object->getId())
->copy(true)
->setSentAt(null)
->setCreatedAt(new \DateTime('now'))
->save();
$this->getSessionUser()->setFlash('message', new FlashSuccess('crud.flash.success.copy'), false,
$this->getConfiguration()->getStorageNamespace());
return $this->redirect($this->generateUrl('TrinityNewsletterBundleNewsletterAdmin_index'));
}
@ -152,43 +378,74 @@ class NewsletterAdminController extends BaseAdminController
{
foreach ($pks as $pk) {
$query->findPK($pk)
->copy(true)
->setSentAt(null)
->setCreatedAt(new \DateTime('now'))
->save();
->copy(true)
->setSentAt(null)
->setCreatedAt(new \DateTime('now'))
->save();
}
}
private function generateNewsletterUser($email)
private function generateUnsubscribeToken($email)
{
if (!$group = GroupQuery::create()->filterByCode('NEWSLETTER')->findOne()) {
throw new \Exception('No newsletter group define. Please create one with the code NEWSLETTER.');
}
$user = new \FOS\UserBundle\Propel\User();
$user->setEmail($email);
$user->setEnabled(false);
$user->setLocked(true);
$user->setUsername(sprintf('%s-%s',$email,date('Y-m-d H:i:s')));
$user->addGroup($group);
$user->save();
$key = '1ag4jf96znv07m459kf29kfZl5I9fnvT8dfg0pza114bM5fg6Kl';
$iv = '3452562488791564';
$token = openssl_encrypt($email, 'aes128', $key, false, $iv);
return $user;
return $token;
}
private function generateUnsubscribeToken()
/**
* @param $form Form
* @param $object Newsletter
* @param Request $request
* @return bool|\Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Trinity\Bundle\AdminBundle\Exception\RequestAdminException
*/
protected function processForm(&$form, &$object, Request $request)
{
$bytes = false;
if (function_exists('openssl_random_pseudo_bytes') && 0 !== stripos(PHP_OS, 'win')) {
$bytes = openssl_random_pseudo_bytes(32, $strong);
if (true !== $strong) {
$bytes = false;
$form->submit($request);
if ($form->isValid()) {
$this->preSave($object);
$uploaded_file = $object->getEmailFile();
if ($uploaded_file instanceof UploadedFile) {
$lines = file($uploaded_file->getPathname());
$emails = "";
$regex2 = '/^([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-'
. '\\x5d\\x7f-\\xff]+|\\x22([^\\x0d\\x22\\x5c\\x80-\\xff]|\\x5c\\x00-'
. '\\x7f)*\\x22)(\\x2e([^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-'
. '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|\\x22([^\\x0d\\x22\\x5c\\x80'
. '-\\xff]|\\x5c\\x00-\\x7f)*\\x22))*\\x40([^\\x00-\\x20\\x22\\x28\\x29'
. '\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+|\\x5b([^'
. '\\x0d\\x5b-\\x5d\\x80-\\xff]|\\x5c\\x00-\\x7f)*\\x5d)(\\x2e([^\\x00-'
. '\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-'
. '\\xff]+|\\x5b([^\\x0d\\x5b-\\x5d\\x80-\\xff]|\\x5c\\x00-\\x7f)*'
. '\\x5d))*$/';
foreach ($lines as $line_num => $line) {
$words = preg_split("/[\s,\;]+/", $line);
foreach ($words as $word) {
if (preg_match($regex2, $word, $matches)) {
$emails .= "\n" . $matches[0];
}
}
}
$object->setEmailListing($object->getEmailListing() . $emails);
}
$object->save();
$this->postSave($object);
return $this->redirect($this->redirectByRequest($request, $object));
}
if (false === $bytes) {
$bytes = hash('sha256', uniqid(mt_rand(), true), true);
}
return base_convert(bin2hex($bytes), 16, 36);
return false;
}
}

View file

@ -1,122 +1,209 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Controller;
namespace Trinity\Bundle\NewsletterBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use FOS\UserBundle\Propel\UserQuery;
use FOS\UserBundle\Propel\GroupQuery;
use FOS\UserBundle\Propel\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use FOS\UserBundle\Propel\UserQuery;
use FOS\UserBundle\Propel\GroupQuery;
use FOS\UserBundle\Propel\User;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotEqualTo;
use Trinity\Bundle\NewsletterBundle\Model\NewsletterQuery;
class NewsletterController extends Controller
class NewsletterController extends Controller
{
/**
* @Route("/newsletter/show/{id}", name="newsletter_preview")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NewsletterBundle\Model\Newsletter")
*/
public function indexAction($object)
{
/**
* @Route("/newsletter/show/{id}", name="newsletter_preview")
* @Template()
* @ParamConverter("object", class="Trinity\Bundle\NewsletterBundle\Model\Newsletter")
*/
public function indexAction($object)
{
if (!$object->getModel()) {
throw $this->createNotFoundException('This newsletter does not have a defined template.');
}
$blocks = array();
foreach ($object->getModel()->getBlocks() as $block) {
$blocks[$block->getName()] = $block;
}
$user = new User();
$user->setUnsubscribeToken('show');
return $this->render(
$object->getModel()->getTemplate(),
array(
'model' => $object->getModel() ,
'blocks' => $blocks ,
'user' => $user,
)
);
if (!$object) {
throw $this->createNotFoundException('This newsletter does not have a defined template.');
}
/**
* @Route("/newsletter/subscribe", name="newsletter_subscribe")
* @Template()
*
*/
public function subscribeAction(Request $request)
{
$defaultData = array(
'email' => ($this->getUser())?$this->getUser()->getEmail():null,
);
$blocks = array();
// TODO : use DataTransformer and specific Type to manage this
$form = $this->container->get('form.factory')->createNamedBuilder('newsletter_subscribe','form', $defaultData)
->setMethod('POST')
->setAction($this->generateUrl('newsletter_subscribe'))
->add('email', 'email', array(
'attr' => array(
'placeholder' => ($this->getUser())?$this->getUser()->getEmail():$this->get('translator')->trans('mail@example.com')
),
'constraints' => array(
new NotBlank(),
new NotEqualTo(array('value'=> $this->get('translator')->trans('mail@example.com')))
)
))
->add('referer','hidden')
->getForm();
$form->handleRequest($request);
if($request->isMethod('POST')) {
if ($form->isValid()) {
$datas = $form->getData();
$this->save(array_merge($datas,array('newsletter' => true)));
$request->getSession()->getFlashBag()->add('success',$this->get('translator')->trans('Thank you for your subscription to our newsletter.'));
$this->redirect($this->generateUrl("newsletter_subscribe"));
}
}
return $this->render(
'TrinityNewsletterBundle:Newsletter:subscribe.html.twig',
array(
'form' => $form->createView()
)
);
foreach ($object->getBlocks() as $block) {
$blocks[$block->getName()] = $block;
}
/**
* @Route("/newsletter/unsubscribe/{token}", name="newsletter_unsubscribe")
* @Template()
*/
public function unsubscribeAction($token)
{
$user = UserQuery::create()->filterByUnsubscribeToken($token)->findOne();
if (!$user) {
throw $this->createNotFoundException('No user found for this token');
}
$blck_group = GroupQuery::create()->filterByCode('BLACKLIST')->findOne();
if (!$blck_group) {
throw $this->createNotFoundException('You must define a group with "BLACKLIST" code in order to allow user\'s unsubscribe');
}
$user->addGroup($blck_group)->save();
}
protected function save(array $datas)
{
$this->get('trinity.user_register')->setCurrentUser($this->getUser());
$user = $this->get('trinity.user_register')->registerUserIfUnknown($datas);
$user = $this->get('trinity.user_register')->updateOptins($datas, $user);
}
return $this->render(
$object->getTemplate(),
array(
'model' => $object ,
'blocks' => $blocks ,
'email' => 'email@show.com',
'unsubscribe_token' => 'show'
)
);
}
/**
* @Route("/newsletter/show_last", name="newsletter_last_preview")
* @Template()
*/
public function lastAction(Request $request)
{
$object = NewsletterQuery::create()
->filterBySentAt(null, \Criteria::ISNOTNULL)
->orderBySentAt(\Criteria::DESC)
->findOne();
if(!$object){
$request->getSession()->getFlashBag()->add('success',$this->get('translator')->trans('No newsletter to show.'));
return $this->redirect($this->generateUrl('homepage'));
}
$blocks = array();
foreach ($object->getBlocks() as $block) {
$blocks[$block->getName()] = $block;
}
return $this->render(
$object->getTemplate(),
array(
'model' => $object ,
'blocks' => $blocks ,
'email' => 'email@show.com',
'unsubscribe_token' => 'show'
)
);
}
/**
* @Route("/newsletter/subscribe", name="newsletter_subscribe")
* @Template()
*
*/
public function subscribeAction(Request $request)
{
$defaultData = array(
'email' => ($this->getUser())?$this->getUser()->getEmail():null,
);
// TODO : use DataTransformer and specific Type to manage this
$form = $this->container->get('form.factory')->createNamedBuilder('newsletter_subscribe','form', $defaultData)
->setMethod('POST')
->setAction($this->generateUrl('newsletter_subscribe'))
->add('email', 'email', array(
'attr' => array(
'placeholder' => ($this->getUser())?$this->getUser()->getEmail():$this->get('translator')->trans('mail@example.com')
),
'constraints' => array(
new NotBlank(),
new NotEqualTo(array('value'=> $this->get('translator')->trans('mail@example.com')))
)
))
->add('referer','hidden')
->getForm();
$form->handleRequest($request);
if($request->isMethod('POST')) {
if ($form->isValid()) {
$datas = $form->getData();
if($this->alreadySubscribed($datas)){
$request->getSession()->getFlashBag()->add('success',$this->get('translator')->trans('You have already subscribed to the newsletter.'));
}else{
$this->save(array_merge($datas, array('newsletter' => true)));
$request->getSession()->getFlashBag()->add('success',$this->get('translator')->trans('Thank you for your subscription to our newsletter.'));
}
$this->redirect($this->generateUrl("newsletter_subscribe"));
}
}
return $this->render(
'TrinityNewsletterBundle:Newsletter:subscribe.html.twig',
array(
'form' => $form->createView()
)
);
}
/**
* @Route("/newsletter/unsubscribe/{token}", name="newsletter_unsubscribe")
* @Template()
*/
public function unsubscribeAction(Request $request, $token)
{
$token = urldecode($token);
$key = '1ag4jf96znv07m459kf29kfZl5I9fnvT8dfg0pza114bM5fg6Kl';
$iv = '3452562488791564';
$email = openssl_decrypt($token, 'aes128', $key, false, $iv);
$user = UserQuery::create()->filterByUnsubscribeToken($token)->findOne();
if (!$user) {
$user = $this->generateNewsletterUser($email);
}
$blck_group = GroupQuery::create()->filterByCode('BLACKLIST')->findOne();
if (!$blck_group) {
throw $this->createNotFoundException('You must define a group with "BLACKLIST" code in order to allow user\'s unsubscribe');
}
$user->addGroup($blck_group)->save();
$this->get('request')->getSession()->getFlashBag()->add('success',$this->get('translator')->trans('Your unsubscribe request is saved.'));
}
protected function save(array $datas)
{
$this->get('trinity.user_register')->setCurrentUser($this->getUser());
$user = $this->get('trinity.user_register')->registerUserIfUnknown($datas);
$this->get('trinity.user_register')->updateOptins($datas, $user);
}
protected function getNewsletterGroups()
{
$groups = array();
$query = GroupQuery::create()->filterByCode('NEWSLETTER\_%',\Criteria::LIKE)->orderByCode();
foreach($query->find() as $group){
$groups[$group->getCode()] = $group->getName();
}
return $groups;
}
protected function alreadySubscribed($datas)
{
if(!isset($datas['email'])){
return false;
}
$count = UserQuery::create()
->filterByEmail($datas['email'])
->useUserGroupQuery()
->useGroupQuery()
->filterByCode('NEWSLETTER')
->endUse()
->endUse()
->count();
return ($count > 0) ? true : false;
}
protected function generateNewsletterUser($email)
{
$user = new \FOS\UserBundle\Propel\User();
$user->setEmail($email);
$user->setEnabled(false);
$user->setLocked(true);
$user->setUsername(sprintf('%s-%s',$email,date('Y-m-d H:i:s')));
$user->save();
return $user;
}
}

View file

@ -22,8 +22,8 @@ class TrinityNewsletterExtension extends Extension
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.xml');
$container->setParameter('trinity_newsletter.newsletter', isset($config['newsletter']) ? $config['newsletter'] : array());
}

View file

@ -22,15 +22,7 @@ class AddBlockFieldsSubscriber implements EventSubscriberInterface
foreach ($data->getConfiguration()->getBlocks() as $block_configuration) {
$type = $block_configuration->getType();
$form->add(
sprintf('block_%s', $block_configuration->getName()),
new $type(),
array(
'attr' => array(
'class' => 'embeded-form',
),
)
);
$form->add(sprintf('block_%s', $block_configuration->getName()), new $type());
}
}
}

View file

@ -1,23 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Form\Type;
use Propel\PropelBundle\Form\BaseAbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ModelFilterType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'Trinity\Bundle\NewsletterBundle\Model\Model',
'name' => 'model_filter',
'csrf_protection' => false,
);
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}
}

View file

@ -1,75 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Form\Type;
use Propel\PropelBundle\Form\BaseAbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use \Trinity\Bundle\NewsletterBundle\Form\EventListener\AddBlockFieldsSubscriber;
class ModelType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'Trinity\Bundle\NewsletterBundle\Model\Model',
'name' => 'model',
);
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add(
'classKey',
'choice',
array(
'choices' => self::getModels(),
'required' => true,
)
);
$builder->add(
'template',
'choice',
array(
'choices' => $this->getTemplates($builder->getData()),
'required' => true,
)
);
$builder->addEventSubscriber(new AddBlockFieldsSubscriber());
}
public function getModels()
{
$models = array();
if (is_array($this->getOption('models'))) {
foreach ($this->getOption('models') as $model => $settings) {
$models[$model] = $settings['title'];
}
}
return $models;
}
public function getTemplates(\Trinity\Bundle\NewsletterBundle\Model\Model $model = null)
{
$templates = array();
if (null !== $model) {
$models = $this->getOption('models');
if (isset($models[$model->getClassKey()])) {
$_templates = $models[$model->getClassKey()]['templates'];
foreach ($_templates as $_template) {
$templates[$_template['template']] = $_template['title'];
}
}
}
return $templates;
}
}

View file

@ -10,6 +10,7 @@ class NewsletterFilterType extends BaseAbstractType
protected $options = array(
'data_class' => 'Trinity\Bundle\NewsletterBundle\Model\Newsletter',
'name' => 'newsletter_filter',
'models' => array(),
'csrf_protection' => false,
);
@ -19,15 +20,15 @@ class NewsletterFilterType extends BaseAbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add('senderName');
$builder->add('senderEmail');
$builder->add('modelId',
'model',
$builder->add(
'classKeyValue',
'choice',
array(
'empty_value' => 'All',
'required' => false,
'class' => 'Trinity\Bundle\NewsletterBundle\Model\Model',
'choices' => self::getModels(),
'label' => 'Modèle',
'required' => false,
'mapped' => false
)
);
@ -45,4 +46,17 @@ class NewsletterFilterType extends BaseAbstractType
)
);
}
public function getModels()
{
$models = array();
if (is_array($this->getOption('models'))) {
foreach ($this->getOption('models') as $model => $settings) {
$models[$model] = $settings['title'];
}
}
return $models;
}
}

View file

@ -4,13 +4,20 @@ namespace Trinity\Bundle\NewsletterBundle\Form\Type;
use Propel\PropelBundle\Form\BaseAbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;
use Trinity\Bundle\NewsletterBundle\Form\EventListener\AddBlockFieldsSubscriber;
use \Trinity\Bundle\NewsletterBundle\Model\ModelQuery;
use Trinity\Component\Form\DataTransformer\StringToFileTransformer;
use Trinity\Component\Form\EventListener\FileDeleteFormListener;
class NewsletterType extends BaseAbstractType
{
protected $options = array(
'data_class' => 'Trinity\Bundle\NewsletterBundle\Model\Newsletter',
'name' => 'newsletter',
'data_class' => 'Trinity\Bundle\NewsletterBundle\Model\Newsletter',
'name' => 'trinity_newsletter_admin_model',
'models' => array(),
'sender_name' => null,
'sender_mail' => null
);
/**
@ -18,20 +25,104 @@ class NewsletterType extends BaseAbstractType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add('senderName');
$builder->add('senderEmail');
$this->setOptions($options);
$builder->add('model',
'model',
$builder->add(
'name',
'text',
array(
'required' => true,
'class' => 'Trinity\Bundle\NewsletterBundle\Model\Model',
'attr' => array(
'data-help' => 'Nom utilisé pour la gestion en BO'
)
)
);
if ($builder->getData()->isNew()) {
$builder->add(
'senderName',
null,
array(
'data' => isset($options['sender_name']) ? $options['sender_name'] : null
)
);
$builder->add(
'senderEmail',
null,
array(
'data' => isset($options['sender_mail']) ? $options['sender_mail'] : null
)
);
} else {
$builder->add('senderName');
$builder->add('senderEmail');
}
$builder->add(
'classKey',
'choice',
array(
'choices' => self::getModels(),
'required' => true,
'attr' => array(
'data-help' => 'Pour éditer le contenu, vous devez enregistrer un modèle de données'
)
)
);
$builder->add(
'template',
'choice',
array(
'label' => 'Mise en page',
'choices' => $this->getTemplates($builder->getData()),
'required' => true,
)
);
$builder->addEventSubscriber(new AddBlockFieldsSubscriber());
$builder->add('emailListing','textarea');
$builder->add(
$builder->create(
'emailFile',
'file',
array(
'label' => 'Fichier email',
'constraints' => array(
new File(),
),
)
)->addModelTransformer(new StringToFileTransformer($builder->getData(), 'emailFile'))
);
$builder->add(
$builder->create(
'emailFileVar',
'file',
array(
'label' => 'CSV email',
'constraints' => array(
new File(),
),
'attr' => array(
'data-help' => 'Fichier CSV avec variables au format suivant : email; var1; var2; ...'
)
)
)->addModelTransformer(new StringToFileTransformer($builder->getData(), 'emailFileVar'))
);
$builder->addEventSubscriber(
new FileDeleteFormListener(
$builder->getFormFactory(),
array(
'emailFile',
'emailFileVar',
)
)
);
$builder->add(
'groups',
'model',
@ -42,4 +133,36 @@ class NewsletterType extends BaseAbstractType
)
);
}
public function getModels()
{
$models = array();
if (is_array($this->getOption('models'))) {
foreach ($this->getOption('models') as $model => $settings) {
$models[$model] = $settings['title'];
}
}
return $models;
}
public function getTemplates(\Trinity\Bundle\NewsletterBundle\Model\Newsletter $model = null)
{
$templates = array();
if (null !== $model) {
$models = $this->getOption('models');
if (isset($models[$model->getClassKey()])) {
$_templates = $models[$model->getClassKey()]['templates'];
foreach ($_templates as $_template) {
$templates[$_template['template']] = $_template['title'];
}
}
}
return $templates;
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseBlockVersion;
class BlockVersion extends BaseBlockVersion
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseBlockVersionPeer;
class BlockVersionPeer extends BaseBlockVersionPeer
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseBlockVersionQuery;
class BlockVersionQuery extends BaseBlockVersionQuery
{
}

View file

@ -1,142 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModel;
use Trinity\Bundle\NewsletterBundle\Configuration\ModelConfiguration;
class Model extends BaseModel
{
protected $blocks = array();
protected $configuration = null;
protected $object;
public function getConfiguration()
{
return $this->configuration;
}
protected function hasBlock($d)
{
return isset($this->blocks[is_object($d) ? $d->getName() : $d]);
}
public function setBlock(Block $block)
{
$block->setModelId($this->getId());
$this->blocks[$block->getName()] = $block;
return $this;
}
public function __construct($template = null)
{
if ($template) {
$this->setTemplate($template);
}
parent::__construct();
$this->configuration = new ModelConfiguration();
}
public function __toString()
{
return $this->name;
}
public function getTemplating()
{
return $this->templating;
}
public function setTemplating($templating)
{
$this->templating = $templating;
return $this;
}
public function save(\PropelPDO $con = null)
{
parent::save($con);
if (!empty($this->blocks)) {
foreach ($this->blocks as $block) {
$block->save($con);
}
} else {
foreach ($this->getConfiguration()->getBlocks() as $block_configuration) {
$this->getBlock($block_configuration->getName())->save($con);
}
}
return $this;
}
public function getBlock($name)
{
if (!$this->getId()) {
return $this->getNewBlock($name);
}
$qBlock = BlockQuery::create()->filterByName($name)->filterByModelId($this->getId())->findOne();
$block = $qBlock ? $qBlock : $this->getNewBlock($name, $this->getId());
if (!$this->hasBlock($block->getName())) {
$this->setBlock($block);
}
return $block;
}
public function getBlockTitle()
{
return $this->getBlock('title');
}
public function getBlockSubtitle()
{
return $this->getBlock('subtitle');
}
public function getBlockContent()
{
return $this->getBlock('content');
}
public function setBlockTitle(Block $block)
{
return $this->setBlock($block);
}
public function setBlockSubtitle(Block $block)
{
return $this->setBlock($block);
}
public function setBlockContent(Block $block)
{
return $this->setBlock($block);
}
protected function getNewBlock($name, $modelId = null)
{
$type = $this->getConfiguration()->getBlock($name)->getType();
$form = new $type();
$form_model = $form->getOption('data_class') ? $form->getOption('data_class') : 'Block';
$block = new $form_model();
$block->setname($name);
if (null !== $modelId) {
$block->setModelId($modelId);
}
return $block;
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModelPeer;
class ModelPeer extends BaseModelPeer
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModelQuery;
class ModelQuery extends BaseModelQuery
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModelVersion;
class ModelVersion extends BaseModelVersion
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModelVersionPeer;
class ModelVersionPeer extends BaseModelVersionPeer
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseModelVersionQuery;
class ModelVersionQuery extends BaseModelVersionQuery
{
}

View file

@ -2,37 +2,49 @@
namespace Trinity\Bundle\NewsletterBundle\Model;
use Trinity\Bundle\NewsletterBundle\Configuration\ModelConfiguration;
use Trinity\Bundle\NewsletterBundle\Model\om\BaseNewsletter;
use \FOS\UserBundle\Propel\UserQuery;
use \FOS\UserBundle\Propel\GroupQuery;
use \FOS\UserBundle\Propel\UserPeer;
use Trinity\Component\Utils\Propel;
use WD\Component\Csv\CsvParser;
class Newsletter extends BaseNewsletter
{
public function __toString()
{
if($this->sent_at) {
return sprintf('%s envoyé le : %s',$this->name,$this->getSentAt('d/m/Y H:i:s'));
if ($this->sent_at) {
return sprintf('%s envoyé le : %s', $this->name, $this->getSentAt('d/m/Y H:i:s'));
}
return sprintf('%s modifier le : %s',$this->name,$this->getUpdatedAt('d/m/Y H:i:s'));
return sprintf('%s modifier le : %s', $this->name, $this->getUpdatedAt('d/m/Y H:i:s'));
}
//************** Système d'envoi **************************
public function getRecipients()
{
$email_list = explode(',', $this->getEmailListing());
$email_list = $this->splitEmailList($this->getEmailListing());
$users_mail = $this->getUserByGroups();
return array_diff(
array_unique(
array_merge(
$email_list,
$users_mail)
),
$this->getUnsubscribed()
);
$recipients_array = array_unique(array_merge($email_list, $users_mail));
$this->setRecipientsNumber(count($recipients_array));
$emails = array_diff($recipients_array, $this->getUnsubscribed());
$this->setBlacklistNumber($this->getRecipientsNumber() - count($emails));
$recipients = filter_var_array($emails, FILTER_VALIDATE_EMAIL);
foreach ($recipients as $key => $value) {
if (empty($value) || $value == false) {
unset($recipients[$key]);
}
}
return $recipients;
}
private function getUnsubscribed()
public function getUnsubscribed()
{
$blck_group = GroupQuery::create()->filterByCode('BLACKLIST')->findOne();
@ -45,7 +57,7 @@ class Newsletter extends BaseNewsletter
private function getUserByGroups()
{
if (!$this->getGroups()) {
if (!$this->getGroups() || $this->countGroups() == 0) {
return array();
}
@ -64,4 +76,278 @@ class Newsletter extends BaseNewsletter
return $user_query->find()->toArray();
}
private function splitEmailList($listing)
{
preg_match_all('`([\w.-]+@[\w.-]+\.[a-z]{2,6})`i', $listing, $matchesarray, PREG_SET_ORDER);
$lists = array();
if (!empty($matchesarray)) {
foreach ($matchesarray as $matches) {
$lists[] = $matches[1];
}
}
return $lists;
}
// *********** Variable dynamique dans CSV *************
public function uploadEmailFileVar()
{
if (null === $this->email_file_var && !$this->delete_email_file_var && null !== $this->rollback_email_file_var) {
$this->email_file_var = $this->rollback_email_file_var; // keep the file
return true;
}
if (null === $this->email_file_var || !is_object($this->email_file_var)) {
return true; // no file to upload
}
//Delete old file on overload
$this->removeEmailFileVar();
$filename = $this->getNewFilename($this->email_file_var->guessExtension());
$this->email_file_var_file = $this->email_file_var;
$this->has_uploaded_email_file_var = true;
$this->email_file_var = $filename;
if ($this->has_uploaded_email_file_var) {
$filename = $this->email_file_var_file->getRealPath();
$parser = new CsvParser($filename, ';', '"', '\\', true);
$parser->parse();
$legend = $parser->getLegend();
$text = "Vous avez chargez un fichier CSV avec des variables. Ces variables sont accessibles dans les blocks de contenus. <br>Voici la liste exhaustive des variables disponibles : <ul>";
foreach ($legend as $term) {
$text .= "<li>" . $this->tokenize($term) . "</li>";
}
$text .= "</ul>";
$unsubscribed = $this->getUnsubscribed();
foreach ($parser->getDatas() as $k => $line) {
$email = trim($line[0]);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$no_complient[$k] = $email;
}
if (in_array($email, $unsubscribed)) {
$blacklisted[$k] = $email;
}
}
if (isset($no_complient)) {
$text .= "<br>Votre fichier contient des adresses emails invalide, voici la liste: <ul>";
foreach ($no_complient as $line => $email) {
$text .= "<li>Ligne " . ($line + 2) . ' : ' . $email . "</li>";
}
$text .= "</ul>";
}
if (isset($blacklisted)) {
$text .= "<br>Votre fichier contient des adresses emails présent dans les désinscrit, voici la liste: <ul>";
foreach ($blacklisted as $line => $email) {
$text .= "<li>Ligne " . ($line + 2) . ' : ' . $email . "</li>";
}
$text .= "</ul>";
}
$this->setEmailVarDesc($text);
}
}
public function tokenize($term)
{
setlocale(LC_CTYPE, 'fr_FR.utf8');
$var = $term;
if (function_exists('iconv')) {
$var = iconv('utf-8', 'us-ascii//TRANSLIT', $var);
}
// lowercase
if (function_exists('mb_strtolower')) {
$var = mb_strtolower($var);
} else {
$var = strtolower($var);
}
// remove accents resulting from OSX's iconv
$var = str_replace(array('\'', '`', '^'), '', $var);
// replace non letter or digits with separator
$var = preg_replace('/\W+/', '_', $var);
// trim
$var = trim($var, '_');
return '%%' . $var . '%%';
}
//************ Templating et modèle ********************
protected $blocks = array();
protected $configuration = null;
protected $templating = null;
protected $object;
public function __construct($template = null)
{
if ($template) {
$this->setTemplate($template);
}
parent::__construct();
$this->configuration = new ModelConfiguration();
}
public function getConfiguration()
{
return $this->configuration;
}
protected function hasBlock($d)
{
return isset($this->blocks[is_object($d) ? $d->getName() : $d]);
}
public function setBlock(Block $block)
{
$block->setNewsletterId($this->getId());
$this->blocks[$block->getName()] = $block;
return $this;
}
public function getTemplating()
{
return $this->templating;
}
public function setTemplating($templating)
{
$this->templating = $templating;
return $this;
}
public function save(\PropelPDO $con = null)
{
parent::save($con);
if (!empty($this->blocks)) {
foreach ($this->blocks as $block) {
$block->save($con);
}
} else {
foreach ($this->getConfiguration()->getBlocks() as $block_configuration) {
$this->getBlock($block_configuration->getName())->save($con);
}
}
return $this;
}
public function getBlock($name)
{
if (!$this->getId()) {
return $this->getNewBlock($name);
}
$qBlock = BlockQuery::create()->filterByName($name)->filterByNewsletterId($this->getId())->findOne();
$block = $qBlock ? $qBlock : $this->getNewBlock($name, $this->getId());
if (!$this->hasBlock($block->getName())) {
$this->setBlock($block);
}
return $block;
}
public function getBlockTitle()
{
return $this->getBlock('title');
}
public function getBlockSubtitle()
{
return $this->getBlock('subtitle');
}
public function getBlockContent()
{
return $this->getBlock('content');
}
public function getBlockSubject()
{
return $this->getBlock('subject');
}
public function setBlockTitle(Block $block)
{
return $this->setBlock($block);
}
public function setBlockSubtitle(Block $block)
{
return $this->setBlock($block);
}
public function setBlockContent(Block $block)
{
return $this->setBlock($block);
}
public function setBlockSubject(Block $block)
{
return $this->setBlock($block);
}
protected function getNewBlock($name, $newsletterId = null)
{
$type = $this->getConfiguration()->getBlock($name)->getType();
$form = new $type();
$form_model = $form->getOption('data_class') ? $form->getOption('data_class') : 'Block';
$block = new $form_model();
$block->setname($name);
if (null !== $newsletterId) {
$block->setNewsletterId($newsletterId);
}
return $block;
}
//********** Affichage BO ***********
public function getRecipientsGroups()
{
return $this->getGroups();
}
public function getStats()
{
return $this;
}
public function getSubject()
{
$subject = $this->getBlock('subject');
return ($subject) ? $subject : $this->getName();
}
}

View file

@ -6,4 +6,10 @@ use Trinity\Bundle\NewsletterBundle\Model\om\BaseNewsletterQuery;
class NewsletterQuery extends BaseNewsletterQuery
{
public function filterByClassKeyValue($value)
{
$value = str_replace('%','',$value);
return $this->filterByClassKey($value);
}
}

View file

@ -0,0 +1,34 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Newsletter;
use Trinity\Bundle\NewsletterBundle\Model\Block;
use Trinity\Bundle\NewsletterBundle\Model\Newsletter;
class ModelOneContent extends Newsletter
{
public function __construct($template = null)
{
parent::__construct(null !== $template ? $template : 'TrinityNewsletterBundle:Default:index.html.twig');
}
public function getConfiguration()
{
return $this->configuration
->setBlock('subject', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('title', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('subtitle', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('content1', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
;
}
public function getBlockContent1()
{
return $this->getBlock('content1');
}
public function setBlockContent1(Block $block)
{
return $this->setBlock($block);
}
}

View file

@ -1,10 +1,11 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Model;
namespace Trinity\Bundle\NewsletterBundle\Newsletter;
use Trinity\Bundle\NewsletterBundle\Model\Block;
use Trinity\Bundle\NewsletterBundle\Model\Newsletter;
class DefaultModel extends Model
class ModelThreeContent extends Newsletter
{
public function __construct($template = null)
{
@ -14,12 +15,13 @@ class DefaultModel extends Model
public function getConfiguration()
{
return $this->configuration
->setBlock('subject', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('title', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('subtitle', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('content1', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
->setBlock('content2', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
->setBlock('content3', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
;
;
}
public function getBlockContent1()

View file

@ -0,0 +1,50 @@
<?php
namespace Trinity\Bundle\NewsletterBundle\Newsletter;
use Trinity\Bundle\NewsletterBundle\Model\Block;
use Trinity\Bundle\NewsletterBundle\Model\Newsletter;
class ModelTwoContent extends Newsletter
{
public function __construct($template = null)
{
parent::__construct(null !== $template ? $template : 'TrinityNewsletterBundle:Default:index.html.twig');
}
public function getConfiguration()
{
return $this->configuration
->setBlock('subject', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('title', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('subtitle', 'Trinity\Bundle\NewsletterBundle\Form\Type\BlockType')
->setBlock('content1', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
->setBlock('content2', 'Trinity\Bundle\NewsletterBundle\Form\Type\TinymceAdvancedBlockType')
;
}
public function getBlockContent1()
{
return $this->getBlock('content1');
}
public function setBlockContent1(Block $block)
{
return $this->setBlock($block);
}
public function getBlockContent2()
{
return $this->getBlock('content2');
}
public function setBlockContent2(Block $block)
{
return $this->setBlock($block);
}
public function getBlockContent3()
{
return $this->getBlock('content3');
}
}

View file

@ -1,64 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<database name="default" namespace="Trinity\Bundle\NewsletterBundle\Model" defaultIdMethod="native" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xsd.propelorm.org/1.6/database.xsd">
<!-- @TODO : add recipients managing system -->
<table name="nws_newsletter" phpName="Newsletter">
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true" />
<column name="name" type="VARCHAR" required="true" size="255" />
<column name="template" type="VARCHAR" required="true" size="255" /> <!-- modele de donnée -->
<column name="class_key" type="VARCHAR" size="255" inheritance="single" /> <!-- modele de mise en page -->
<column name="sender_name" type="VARCHAR" size="255"/>
<column name="sender_email" type="VARCHAR" size="255"/>
<column name="model_id" type="integer" />
<column name="email_listing" type="longvarchar" /> <!-- listing de mail injecté manuellement -->
<column name="sent_at" type="timestamp" />
<behavior name="timestampable" />
<foreign-key foreignTable="nws_model" onDelete="none">
<reference local="model_id" foreign="id" />
</foreign-key>
<column name="email_listing" type="longvarchar" /> <!-- listing de mail injecté manuellement -->
<column name="email_file" type="varchar" /> <!-- listing de mail injecté par fichier -->
<column name="email_file_var" type="varchar" /> <!-- listing de mail injecté par fichier avec variables -->
<column name="sent_at" type="timestamp" />
<column name="email_var_desc" type="longvarchar" /> <!-- description des varaibles si email_file_var renseigné -->
<column name="recipients_number" type="INTEGER" /> <!-- nombre de destinataire -->
<column name="blacklist_number" type="INTEGER" /> <!-- nombre de destinataire présent dans la blacklist -->
<behavior name="uploadable">
<parameter name="fields" value="email_file, email_file_var"/>
<parameter name="paths" value="uploads/newsletter/email, uploads/newsletter/email"/>
</behavior>
<behavior name="timestampable" />
</table>
<table name="nws_newsletter_recipients" phpName="NewsletterRecipients" isCrossRef="true">
<column name="nws_newsletter_id" type="integer" required="true" primaryKey="true" />
<column name="fos_group_id" type="integer" required="true" primaryKey="true" />
<foreign-key foreignTable="nws_newsletter">
<reference local="nws_newsletter_id" foreign="id" />
<column name="nws_newsletter_id" type="integer" required="true" primaryKey="true"/>
<column name="fos_group_id" type="integer" required="true" primaryKey="true"/>
<foreign-key foreignTable="nws_newsletter" onDelete="cascade">
<reference local="nws_newsletter_id" foreign="id"/>
</foreign-key>
<foreign-key foreignTable="fos_group">
<reference local="fos_group_id" foreign="id" />
<foreign-key foreignTable="fos_group" onDelete="cascade">
<reference local="fos_group_id" foreign="id"/>
</foreign-key>
</table>
<table name="nws_model" phpName="Model">
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true" />
<column name="name" type="VARCHAR" required="true" size="255" />
<column name="template" type="VARCHAR" required="true" size="255" /> <!-- modele de donnée -->
<column name="class_key" type="VARCHAR" size="255" inheritance="single" /> <!-- modele de mise en page -->
<behavior name="timestampable" />
<behavior name="versionable">
<parameter name="log_created_at" value="true" />
<parameter name="log_created_by" value="true" />
</behavior>
</table>
<table name="nws_block" phpName="Block">
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true" />
<column name="name" type="VARCHAR" required="true" size="255" />
<column name="value" type="LONGVARCHAR" />
<column name="class_key" type="VARCHAR" size="255" inheritance="single" />
<column name="template" size="255" />
<column name="model_id" type="INTEGER" />
<column name="id" type="INTEGER" required="true" primaryKey="true" autoIncrement="true" />
<column name="name" type="VARCHAR" required="true" size="255" />
<column name="value" type="LONGVARCHAR" />
<column name="class_key" type="VARCHAR" size="255" inheritance="single" />
<column name="template" size="255" />
<column name="newsletter_id" type="INTEGER" />
<behavior name="timestampable" />
<behavior name="versionable">
<parameter name="log_created_at" value="true" />
<parameter name="log_created_by" value="true" />
</behavior>
<foreign-key foreignTable="nws_model" onDelete="cascade">
<reference local="model_id" foreign="id" />
<foreign-key foreignTable="nws_newsletter" onDelete="cascade">
<reference local="newsletter_id" foreign="id" />
</foreign-key>
</table>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="trinty_newsletter.newsletter_type.class">Trinity\Bundle\NewsletterBundle\Form\Type\NewsletterType</parameter>
</parameters>
<services>
<service id="trinity.newsletter.form.newsletter_type" class="%trinty_newsletter.newsletter_type.class%">
<tag name="form.type" alias="trinity_newsletter_admin_model" />
</service>
</services>
</container>

View file

@ -1,7 +0,0 @@
parameters:
# trinity_newsletter.example.class: Trinity\Bundle\NewsletterBundle\Example
services:
# trinity_newsletter.example:
# class: %trinity_newsletter.example.class%
# arguments: [@service_id, "plain_value", %parameter%]

View file

@ -56,7 +56,7 @@
</trans-unit>
<trans-unit id="14">
<source>New newsletter model</source>
<target>Nouveau modèle de newsletter</target>
<target>NNouvelle lettre d'information</target>
</trans-unit>
<trans-unit id="15">
<source>Content</source>
@ -76,16 +76,28 @@
</trans-unit>
<trans-unit id="19">
<source>Available newsletter models</source>
<target>Modèle de newsletter disponible</target>
<target>Lettres d'informations disponible</target>
</trans-unit>
<trans-unit id="20">
<source>Edit newsletter model "%name%"</source>
<target>Modifier le modèle de newsletter "%name%"</target>
<target>Modifier la lettre d'information "%name%"</target>
</trans-unit>
<trans-unit id="21">
<source>model</source>
<target>Modèle</target>
</trans-unit>
<trans-unit id="22">
<source>name</source>
<target>Nom</target>
</trans-unit>
<trans-unit id="23">
<source>Newsletters</source>
<target>Lettres d'informations</target>
</trans-unit>
<trans-unit id="24">
<source>Block subject</source>
<target>Sujet</target>
</trans-unit>
</body>
</file>
</xliff>

View file

@ -8,20 +8,24 @@
<h2>{{ macros.render_nws_block(blocks['subtitle']) }}</h2>
<table>
<tbody>
<tr>
<td>{{ macros.render_nws_block(blocks['content1']) }}</td>
<tr>
<td>{{ macros.render_nws_block(blocks['content1']) }}</td>
{% if 'content2' in blocks|keys %}
<td>{{ macros.render_nws_block(blocks['content2']) }}</td>
</tr>
{% endif %}
</tr>
{% if 'content3' in blocks|keys %}
<tr>
<td colspan="2">{{ macros.render_nws_block(blocks['content3']) }}</td>
</tr>
{% endif %}
</tbody>
<tfoot>
<tr>
<td colspan="2">
<tr>
<td colspan="2">
Si vous voulez vous désabonnez de la newsletter,
<a href="{{ url('newsletter_unsubscribe',{ token : user.unsubscribeToken }) }}">cliquez ici</a>.
</td>
</tr>
<a href="{{ url('newsletter_unsubscribe',{ token : unsubscribe_token|url_encode }) }}">cliquez ici</a>.
</td>
</tr>
</tfoot>
</table>

View file

@ -1,9 +0,0 @@
{% extends "TrinityAdminBundle:BaseAdmin:edit.html.twig" %}
{% block javascripts %}
{{ parent() }}
<script>
$('.embeded-form label').remove();
</script>
{% endblock %}

View file

@ -1,115 +0,0 @@
{% extends "TrinityAdminBundle:BaseAdmin:index.html.twig" %}
{% block body %}
{% set colspan = 0 %}
<div id="crud" class="with-panel">
<h3 class="crud-title">{{ title|trans() }}</h3>
<div class="row container-fluid">
{% render controller(bundle_name ~ ":" ~ controller_name ~ ":flash") %}
{% include "TrinityAdminBundle:BaseAdmin:pager.html.twig" %}
{% for action,template in index_actions %}
{% include template %}
{% endfor %}
<div class="clear"></div>
<div class="sep"></div>
</div>
<div class="row container-fluid">
<form id="crud-datas" action="{{ path(route_prefix ~ 'batch') }}" method="post" {{ form_enctype(form_batch) }}>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
{% if batch_actions %}
{% set colspan = colspan + 1 %}
<th class="batch_th">
<input type="checkbox" />
</th>
{% endif %}
{% for field in fields %}
<th class="cols_th">
{% if fieldsnames %}
{% set label = fieldsnames[field.name] is defined ? fieldsnames[field.name] : field.name %}
{% else %}
{% set label = field.name|trans() %}
{% endif %}
{% set sort = (app.request.query.get('sort') == field.name ~ ":asc") ? field.name ~ ":desc" : field.name ~ ":asc" %}
<a href="{{ path(route_prefix ~ "index", { page: pager.currentPage, sort: sort }) }}">{{ label }}</a>
</th>
{% set colspan = colspan + 1 %}
{% endfor %}
<th class="actions_th">{% set colspan = colspan + 1 %}</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="{{ colspan }}">
{% if rankable %}
<p class="rankable"><i class="icon-info-sign"></i> {{ 'crud.list.rankable'|trans({}, 'TrinityAdminBundle') }}</p>
{% endif %}
<div class="pull-left">
{% if batch_actions %}
<p class="pull-left espace-right">
{{ 'crud.list.actions.batch'|trans({}, 'TrinityAdminBundle') }} {{ form_widget(form_batch["action"]) }} <input type="submit" value="{{ 'crud.list.actions.batchgo'|trans({}, 'TrinityAdminBundle') }}" class="btn btn-mini btn-primary" />
</p>
{% endif %}
{% if pager|length %}
{{ form_widget(form_batch._token) }}
{% endif %}
</div>
<div class="espace-top2">
{% include "TrinityAdminBundle:BaseAdmin:pager.html.twig" %}
{% for action, template in index_actions %}
{% include template %}
{% endfor %}
</div>
</th>
</tr>
</tfoot>
<tbody>
{% for object in pager %}
<tr {% if rankable %}data-id="{{ object.id }}"{% endif %}>
{% if batch_actions %}
<td class="batch_td">
<!-- {{ form_widget(form_batch["objects"]) }} -->
<input type="checkbox" name="{{ form_batch.vars.full_name }}[objects][]" value="{{ object.getId }}" />
</td>
{% endif %}
{% for key, field in fields %}
<td class="cols_td">
{% set href = list_actions.edit is defined and key == 0 ? path(route_prefix ~ "edit", { id: object.id }) : false %}
{% if field.name == 'class_key' %}
{{ models[object.classKey]['title'] }}
{% elseif field.name == 'template' %}
{{ templates[object.classKey][object.template] }}
{% else %}
{{ field_render(object, field.method, field.template, href) }}
{% endif %}
</td>
{% endfor %}
<td class="actions_td">
{% for action, template in list_actions %}
{% include template %}
{% endfor%}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
</div>
{% endblock %}

View file

@ -1 +0,0 @@
{% extends "TrinityAdminBundle:BaseAdmin:new.html.twig" %}

View file

@ -11,6 +11,7 @@
{{ form_errors(form) }}
{{ form_row(form.email) }}
{{ form_widget(form.groups) }}
<input type="submit" value="{{ "S'inscrire"|trans }}" />

View file

@ -1 +1,26 @@
{% extends "TrinityAdminBundle:BaseAdmin:edit.html.twig" %}
{% block body %}
<div id="crud" class="with-panel">
{% include "TrinityAdminBundle:BaseAdmin:editTop.html.twig" %}
<div class="row container-fluid">
<div>
<br>
{% if object.getEmailVarDesc() %}
{{ object.getEmailVarDesc()|raw }}
{% endif %}
</div>
{% include "TrinityAdminBundle:BaseAdmin:flash.html.twig" %}
{% include "TrinityAdminBundle:BaseAdmin:editForm.html.twig" %}
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script>
$('#tab_2 .controls label').remove();
</script>
{% endblock %}

View file

@ -1 +1,117 @@
{% extends "TrinityAdminBundle:BaseAdmin:index.html.twig" %}
{% block body %}
{% set colspan = 0 %}
<div id="crud" class="with-panel">
<h3 class="crud-title">{{ title|trans() }}</h3>
<div class="row container-fluid">
{% render controller(bundle_name ~ ":" ~ controller_name ~ ":flash") %}
{% include "TrinityAdminBundle:BaseAdmin:pager.html.twig" %}
{% for action,template in index_actions %}
{% include template %}
{% endfor %}
<div class="clear"></div>
<div class="sep"></div>
</div>
<div class="row container-fluid">
<form id="crud-datas" action="{{ path(route_prefix ~ 'batch') }}" method="post" {{ form_enctype(form_batch) }}>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
{% if batch_actions %}
{% set colspan = colspan + 1 %}
<th class="batch_th">
<input type="checkbox" />
</th>
{% endif %}
{% for field in fields %}
<th class="cols_th">
{% if fieldsnames %}
{% set label = fieldsnames[field.name] is defined ? fieldsnames[field.name] : field.name %}
{% else %}
{% set label = field.name|trans() %}
{% endif %}
{% set sort = (app.request.query.get('sort') == field.name ~ ":asc") ? field.name ~ ":desc" : field.name ~ ":asc" %}
<a href="{{ path(route_prefix ~ "index", { page: pager.currentPage, sort: sort }) }}">{{ label }}</a>
</th>
{% set colspan = colspan + 1 %}
{% endfor %}
<th class="actions_th">{% set colspan = colspan + 1 %}</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="{{ colspan }}">
{% if rankable %}
<p class="rankable"><i class="icon-info-sign"></i> {{ 'crud.list.rankable'|trans({}, 'TrinityAdminBundle') }}</p>
{% endif %}
<div class="pull-left">
{% if batch_actions %}
<p class="pull-left espace-right">
{{ 'crud.list.actions.batch'|trans({}, 'TrinityAdminBundle') }} {{ form_widget(form_batch["action"]) }} <input type="submit" value="{{ 'crud.list.actions.batchgo'|trans({}, 'TrinityAdminBundle') }}" class="btn btn-mini btn-primary" />
</p>
{% endif %}
{% if pager|length %}
{{ form_widget(form_batch._token) }}
{% endif %}
</div>
<div class="espace-top2">
{% include "TrinityAdminBundle:BaseAdmin:pager.html.twig" %}
{% for action, template in index_actions %}
{% include template %}
{% endfor %}
</div>
</th>
</tr>
</tfoot>
<tbody>
{% for object in pager %}
<tr {% if rankable %}data-id="{{ object.id }}"{% endif %}>
{% if batch_actions %}
<td class="batch_td">
<!-- {{ form_widget(form_batch["objects"]) }} -->
<input type="checkbox" name="{{ form_batch.vars.full_name }}[objects][]" value="{{ object.getId }}" />
</td>
{% endif %}
{% for key, field in fields %}
<td class="cols_td">
{% set href = list_actions.edit is defined and key == 0 ? path(route_prefix ~ "edit", { id: object.id }) : false %}
{% if field.name == 'class_key' %}
{{ models[object.classKey]['title'] }}
{% elseif field.name == 'template' %}
{% if templates[object.classKey] is defined and object.template %}
{{ templates[object.classKey][object.template] }}
{% endif %}
{% else %}
{{ field_render(object, field.method, field.template, href) }}
{% endif %}
</td>
{% endfor %}
<td class="actions_td" width="100px;">
{% for action, template in list_actions %}
{% include template %}
{% endfor%}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
</div>
{% endblock %}

View file

@ -1,3 +1,3 @@
<a target="_blank" href="{{ path('newsletter_preview', { id : object.id }) }}">
<a target="_blank" href="{{ path('newsletter_preview', { id : object.id }) }}" title="Voir">
<i class="icon-eye-open"></i>
</a>

View file

@ -1,5 +1,11 @@
&nbsp;
&nbsp;
{% if object.sentAt == null %}
<a href="{{ path('TrinityNewsletterBundleNewsletterAdmin_send',{ id : object.id }) }}">
<i class="icon-envelope"></i>
</a>
<a href="{{ path('TrinityNewsletterBundleNewsletterAdmin_send',{ id : object.id }) }}" title="Envoyer">
<i class="icon-envelope"></i>
</a>
{% else %}
<a href="{{ path('TrinityNewsletterBundleNewsletterAdmin_copy',{ id : object.id }) }}" title="Copier">
<i class="icon-file"></i>
</a>
{% endif %}

View file

@ -0,0 +1,9 @@
{% if value %}
<ul style="margin: 0;">
{% for group in value %}
<li>
{{ group.name }}
</li>
{% endfor %}
</ul>
{% endif %}

View file

@ -0,0 +1,3 @@
{% if object.sentAt %}
{{ object.recipientsNumber }} destinataires dont {{ object.blacklistNumber }} désinscrit (blacklist)
{% endif %}

View file

@ -68,14 +68,20 @@ class BasicNotifier extends AbstractNotifier
return $user;
}
public function notify($template, array $data = array())
public function notify($template = null, array $data = array())
{
$notification = $this->getNewNotification();
$template = $this->loadTemplate($template);
$data = array_merge($this->getDefaultData(), $data);
$content = $this->twig->render($template->getContent(), $data);
$logContent = $this->twig->render($template->getLogContent(), $data);
$content = '';
if($template) {
$template = $this->loadTemplate($template);
$data = array_merge($this->getDefaultData(), $data);
$content = $this->twig->render($template->getContent(), $data);
$logContent = $this->twig->render($template->getLogContent(), $data);
} else {
$logContent = implode(' / ', $data);
}
$notification
->setContentRender($content)

View file

@ -43,3 +43,6 @@
</table>
</div>
{% endblock body %}
{% block javascripts %}
{% endblock %}