Merge branch 'master' of ../application-blanche
authorSébastien CHAZALLET <s.chazallet@gmail.com>
Fri, 16 Nov 2012 10:34:10 +0000 (11:34 +0100)
committerSébastien CHAZALLET <s.chazallet@gmail.com>
Fri, 16 Nov 2012 10:34:10 +0000 (11:34 +0100)
35 files changed:
composer.json
composer.phar
config/application.config.php
config/autoload/global.php
data/images/1/ama_dablam.jpg [new file with mode: 0644]
data/images/1/nupse.jpg [new file with mode: 0644]
data/images/1/panorama.jpg [new file with mode: 0644]
data/images/2/P9090395.jpg [new file with mode: 0644]
data/images/2/P9090577.jpg [new file with mode: 0644]
data/images/2/P9110931.jpg [new file with mode: 0644]
data/images/2/P9110957.jpg [new file with mode: 0644]
data/images/3/pelemele.jpg [new file with mode: 0644]
data/jeu_essai.db [new file with mode: 0644]
data/scripts/data.sql [new file with mode: 0644]
data/scripts/schema.sql [new file with mode: 0644]
module/Galerie/Module.php [new file with mode: 0644]
module/Galerie/autoload_classmap.php [new file with mode: 0644]
module/Galerie/config/module.config.php [new file with mode: 0644]
module/Galerie/language/fr_FR.mo [new file with mode: 0644]
module/Galerie/language/fr_FR.po [new file with mode: 0644]
module/Galerie/language/val/Zend_Validate_fr_FR.php [new file with mode: 0644]
module/Galerie/src/Galerie/Controller/IndexController.php [new file with mode: 0644]
module/Galerie/src/Galerie/Form/GalerieForm.php [new file with mode: 0644]
module/Galerie/src/Galerie/Model/Galerie.php [new file with mode: 0644]
module/Galerie/src/Galerie/Model/GalerieInfo.php [new file with mode: 0644]
module/Galerie/src/Galerie/Model/GalerieInfoTable.php [new file with mode: 0644]
module/Galerie/src/Galerie/Model/GalerieTable.php [new file with mode: 0644]
module/Galerie/view/galerie/index/del.phtml [new file with mode: 0644]
module/Galerie/view/galerie/index/edit.phtml [new file with mode: 0644]
module/Galerie/view/galerie/index/index.phtml [new file with mode: 0644]
module/Galerie/view/galerie/index/view.phtml [new file with mode: 0644]
server_config/site.alias
server_config/site.vhost
vendor/.gitignore
vendor/zf2biz/Custom/Model/Manager.php

index f534441..9e017e5 100644 (file)
@@ -1,6 +1,6 @@
 {
-    "name": "zf2biz/application-blanche",
-    "description": "Application blanche pour ZF2",
+    "name": "zf2biz/galerie",
+    "description": "Galerie construite à partir de l'Application blanche pour ZF2",
     "license": "BSD-3-Clause",
     "keywords": [
         "framework",
index 661fadd..28635d1 100755 (executable)
Binary files a/composer.phar and b/composer.phar differ
index 6504dea..1dab349 100644 (file)
@@ -2,6 +2,7 @@
 return array(
     'modules' => array(
         'Application',
+        'Galerie',
     ),
     'module_listener_options' => array(
         'config_glob_paths'    => array(
index 104762e..39f8af7 100644 (file)
  * control, so do not include passwords or other sensitive information in this
  * file.
  */
-
 return array(
-    // ...
+    'db' => array(
+        'driver' => 'Pdo',
+        'dsn' => 'sqlite:' . getcwd() . '/data/jeu_essai.db',
+    ),
+    /* Alternative
+    'db' => array(
+        'driver' => 'Pdo_Sqlite',
+        'database' => getcwd() . '/data/jeu_essai.db',
+    ),*/
+    'service_manager' => array(
+        'factories' => array(
+            'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
+        ),
+    ),
 );
diff --git a/data/images/1/ama_dablam.jpg b/data/images/1/ama_dablam.jpg
new file mode 100644 (file)
index 0000000..a2ee0f4
Binary files /dev/null and b/data/images/1/ama_dablam.jpg differ
diff --git a/data/images/1/nupse.jpg b/data/images/1/nupse.jpg
new file mode 100644 (file)
index 0000000..5b9a71c
Binary files /dev/null and b/data/images/1/nupse.jpg differ
diff --git a/data/images/1/panorama.jpg b/data/images/1/panorama.jpg
new file mode 100644 (file)
index 0000000..bd3df02
Binary files /dev/null and b/data/images/1/panorama.jpg differ
diff --git a/data/images/2/P9090395.jpg b/data/images/2/P9090395.jpg
new file mode 100644 (file)
index 0000000..47e948b
Binary files /dev/null and b/data/images/2/P9090395.jpg differ
diff --git a/data/images/2/P9090577.jpg b/data/images/2/P9090577.jpg
new file mode 100644 (file)
index 0000000..0dee226
Binary files /dev/null and b/data/images/2/P9090577.jpg differ
diff --git a/data/images/2/P9110931.jpg b/data/images/2/P9110931.jpg
new file mode 100644 (file)
index 0000000..3c29b7b
Binary files /dev/null and b/data/images/2/P9110931.jpg differ
diff --git a/data/images/2/P9110957.jpg b/data/images/2/P9110957.jpg
new file mode 100644 (file)
index 0000000..eb7d9cf
Binary files /dev/null and b/data/images/2/P9110957.jpg differ
diff --git a/data/images/3/pelemele.jpg b/data/images/3/pelemele.jpg
new file mode 100644 (file)
index 0000000..3f7f9f6
Binary files /dev/null and b/data/images/3/pelemele.jpg differ
diff --git a/data/jeu_essai.db b/data/jeu_essai.db
new file mode 100644 (file)
index 0000000..90fe975
Binary files /dev/null and b/data/jeu_essai.db differ
diff --git a/data/scripts/data.sql b/data/scripts/data.sql
new file mode 100644 (file)
index 0000000..d9a8da7
--- /dev/null
@@ -0,0 +1,56 @@
+PRAGMA foreign_keys = ON;
+
+INSERT INTO user (lastname, firstname, birth, email)
+      SELECT 'Finy', 'Alain', '1962-09-17', 'alain@example.com'
+UNION SELECT 'Mulder', 'Fox', '1980-12-20', 'fox@ailleurs.com'
+UNION SELECT 'Cah', 'Paul', '1972-10-19', 'paul.c@example.com'
+UNION SELECT 'Satch', 'Joe', '1956-07-15', 'john.d@example.com';
+
+
+INSERT INTO contact
+      SELECT 1, 2
+UNION SELECT 1, 3
+UNION SELECT 1, 4
+UNION SELECT 2, 1
+UNION SELECT 2, 3
+UNION SELECT 3, 1;
+
+
+INSERT INTO gallery (id_user, name, description)
+      SELECT 2, 'Pérou', 'Photos des vacances au Pérou, 2011'
+UNION SELECT 1, 'Himalaya', 'Entrainement requis'
+UNION SELECT 2, 'Parapente', 'Photos de vol en parapente';
+
+
+INSERT INTO photo (id_gallery, name, description, filename, extension)
+      SELECT 1, 'Machu Picchu 1', 'Vue d''ensemble du Machu Picchu', 'P9110931', 'jpg'
+UNION SELECT 1, 'Machu Picchu 2', 'Vue depuis la ville', 'P9110957', 'jpg' 
+UNION SELECT 1, 'Paysages 1', 'Un peu désertique', 'P9090395', 'jpg'
+UNION SELECT 1, 'Paysages 2', 'Un peu de verdure', 'P9090577', 'jpg'
+UNION SELECT 2, 'Ama Dablam', 'Sommet à 6856m. Situé au pied de l''Everest et du Lhotse. Signifie "reliquaire de la mère" en référence au pendentif que portent les Sherpanis', 'ama_dablam', 'jpg'
+UNION SELECT 2, 'Nupse', 'Sommet à 7864m', 'nupse', 'jpg'
+UNION SELECT 2, 'Panorama', 'Vue vers l''est depuis le camp d''altitude', 'panorama', 'jpg'
+UNION SELECT 1, 'Lac Titicaca', 'Lac Titicaca', 'lt', 'jpg'
+UNION SELECT 3, 'Pêle-mêle', 'Pêle-mêle de photographies', 'pelemele', 'jpg';
+
+
+INSERT INTO order_form (id_gallery)
+      SELECT 1
+UNION SELECT 2
+UNION SELECT 2;
+
+
+INSERT INTO order_element (id_order_form, id_user, id_photo, quantity)
+      SELECT 1, 1, 1, 1
+UNION SELECT 1, 1, 2, 1
+UNION SELECT 1, 1, 3, 1
+UNION SELECT 1, 1, 4, 1
+UNION SELECT 1, 2, 1, 2
+UNION SELECT 1, 2, 2, 4
+UNION SELECT 1, 1, 2, 1
+UNION SELECT 2, 1, 1, 1
+UNION SELECT 2, 1, 2, 1;
+
+UPDATE order_form SET status='wait' WHERE id IN (1, 2);
+UPDATE order_form SET status='end' WHERE id=1;
+
diff --git a/data/scripts/schema.sql b/data/scripts/schema.sql
new file mode 100644 (file)
index 0000000..14a9f1f
--- /dev/null
@@ -0,0 +1,217 @@
+PRAGMA foreign_keys = ON;
+
+/*
+ * Utilisateur ayant un compte sur l'application
+ */
+CREATE TABLE user (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+       lastname VARCHAR(32) NOT NULL COLLATE NOCASE,
+       firstname VARCHAR(32) NOT NULL COLLATE NOCASE,
+       birth DATE NOT NULL,
+       email VARCHAR(32) NOT NULL UNIQUE COLLATE NOCASE,
+       UNIQUE (lastname, firstname, birth)
+);
+
+CREATE INDEX idx_user_id ON user(id);
+CREATE INDEX idx_user_unique_triptyque ON user(lastname, firstname, birth);
+CREATE INDEX idx_user_email ON user(email);
+CREATE INDEX idx_user_all ON user(id, lastname, firstname, birth, email);
+
+/*
+ * Gestion du carnet de contacts entre utilisateurs
+ * Non réciproque
+ */
+CREATE TABLE contact (
+    id_user_owner INTEGER ASC REFERENCES user(id),
+    id_user_contact INTEGER ASC REFERENCES user(id),
+    PRIMARY KEY (id_user_owner, id_user_contact)
+);
+
+CREATE INDEX idx_contact ON contact(id_user_owner, id_user_contact);
+
+/*
+ * Gallerie de photos (pas de workflow associé)
+ */
+CREATE TABLE gallery (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+    id_user INTEGER REFERENCES user(id),
+    name VARCHAR(32) NOT NULL UNIQUE COLLATE NOCASE,
+    description TEXT NOT NULL,
+    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE INDEX idx_gallery_id ON gallery(id);
+CREATE INDEX idx_gallery_name ON gallery(name);
+CREATE INDEX idx_gallery_user_fk ON gallery(id_user);
+CREATE INDEX idx_gallery_all ON gallery(id, id_user, name, description, created, updated);
+
+/*
+ * Element de gallerie : photographie
+ * Plusieurs photographies sont stockées sur le disque dur, aux formats:
+ * - original   (format de l'appareil photo)
+ * - écran      (format d'affichage de la photo à l'écran)
+ * - miniature  (format d'affichage pour les miniatures de la gallerie)
+ */
+CREATE TABLE photo (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+    id_gallery INTEGER REFERENCES gallery(id),
+    name VARCHAR(16) NOT NULL UNIQUE COLLATE RTRIM,
+    description TEXT NOT NULL,
+    filename VARCHAR(12) NOT NULL COLLATE NOCASE,
+    extension VARCHAR(4) NOT NULL COLLATE NOCASE CHECK (extension IN ('jpg', 'png')),
+    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE INDEX idx_photo_id ON photo(id);
+CREATE INDEX idx_photo_name ON photo(name);
+CREATE INDEX idx_photo_gallery_fk ON photo(id_gallery);
+CREATE INDEX idx_photo_all ON photo(id, id_gallery, name, description, filename, extension, created, updated);
+
+/*
+ * Commande qui dispose d'un workflow:
+ * - le propriétaire de la gallerie ouvre une commande
+ * - tant que la commande est ouverte, les contacts du propriétaire peuvent demander des exemplaire de chaque photo
+ * - après une certaine période, la commande passé au statut en attente; les photos sont en cours de développement
+ * - lorsque la commande est reçue, elle est alors fermée
+ * - tous les contacts du propriétaires passent donc commande en même temps
+ * - le propriétaire peut réouvrir au besoin une nouvelle commande
+ */
+CREATE TABLE order_form (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+    id_gallery UNSIGNED SMALLINT REFERENCES gallery (id),
+    status VARCHAR(4) NOT NULL COLLATE NOCASE CHECK (status IN ('open', 'wait', 'end')) DEFAULT 'open',
+    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    closed TIMESTAMP NOT NULL DEFAULT (datetime('now', '+1 month')),
+    ended TIMESTAMP NULL DEFAULT NULL
+);
+
+CREATE INDEX idx_order_form_id ON order_form(id);
+CREATE INDEX idx_order_form_gallery_fk ON order_form(id_gallery);
+CREATE INDEX idx_order_form_all ON order_form(id, id_gallery, status, created, closed, ended);
+
+/*
+ * élément de commande :
+ * - il n'est pas possible de créer un tel élément lorsque la commande n'est pas ouverte
+ * - il n'est pas possible de passer commande si l'on ne fait pas parti des contacts du propriétaire
+ */
+CREATE TABLE order_element (
+    id_order_form INTEGER REFERENCES order_form(id),
+    id_user INTEGER REFERENCES user(id),
+    id_photo INTEGER REFERENCES photo(id),
+    quantity UNSIGNED SMALLINT DEFAULT 1,
+    PRIMARY KEY (id_user, id_order_form, id_photo)
+);
+
+CREATE INDEX idx_order_element_primary ON order_element(id_order_form, id_user, id_photo);
+CREATE INDEX idx_order_element_all ON order_element(id_order_form, id_user, id_photo, quantity);
+
+/*
+ * à chaque fois que les propriétés d'une gallerie sont modifiées, le champs contenant la date de mise à jour l'est également
+ */
+CREATE TRIGGER gallery_update_management AFTER UPDATE ON gallery
+BEGIN
+    UPDATE gallery SET updated = datetime('now') WHERE id = old.id;
+END;
+
+/*
+ * à chaque fois que les propriétés d'une photographie sont modifiées, le champs contenant la date de mise à jour l'est également ainsi que celui de la gallerie liée
+ */
+CREATE TRIGGER photo_update_management AFTER UPDATE ON photo
+BEGIN
+    UPDATE gallery SET updated = datetime('now') WHERE id = old.id_gallery;
+    UPDATE photo SET updated = datetime('now') WHERE id = old.id;
+END;
+
+/*
+ * à chaque fois qu'une photographie est rajoutée, le champs contenant la date de mise la gallerie liée est mis à jour
+ */
+CREATE TRIGGER photo_insert_management AFTER UPDATE ON photo
+BEGIN
+    UPDATE gallery SET updated = datetime('now') WHERE id = old.id_gallery;
+END;
+
+/*
+ * Gestion du workflow sur une commande: mise à jour de la date de fermeture au changement de statut open vers wait
+ */
+CREATE TRIGGER order_form_update_management_closed AFTER UPDATE OF status ON order_form WHEN old.status='open' AND new.status='wait'
+BEGIN
+    UPDATE order_form SET closed = datetime('now') WHERE id = old.id;
+END;
+
+/*
+ * Gestion du workflow sur une commande: mise à jour de la date de fermeture au changement de statut wait vers end
+ */
+CREATE TRIGGER order_form_update_management_ended AFTER UPDATE OF status ON order_form WHEN old.status='wait' AND new.status='end'
+BEGIN
+    UPDATE order_form SET ended = datetime('now') WHERE id = old.id;
+END;
+
+/*
+ * Gestion du workflow sur une commande: il doit être impossible d'aller en arrière
+ */
+CREATE TRIGGER order_form_update_management_workflow BEFORE UPDATE OF status ON order_form 
+BEGIN
+    SELECT CASE
+        WHEN (old.status='wait' AND new.status='open')
+            OR (old.status='end' AND new.status<>'end')
+        THEN RAISE(ABORT, 'new status do not respect workflow')
+    END;
+END;
+
+/*
+ * Gestion d'un élément de commande: il doit être impossible de modifier uns des clés primaires
+ */
+CREATE TRIGGER order_element_update_management_workflow BEFORE UPDATE OF status ON order_element
+BEGIN
+    SELECT CASE
+        WHEN old.id_order_form <> new.id_order_form
+            OR old.id_user <> new.id_user
+            OR old.id_photo <> new.id_photo
+        THEN RAISE(ABORT, 'bad usage of order element')
+    END;
+END;
+
+/*
+ * Gestion du workflow sur un élément de commande: il doit être impossible de modifier un élément de commande si la commande n'est pas ouverte
+ */
+CREATE TRIGGER order_element_update_management_when_closed BEFORE UPDATE ON order_element
+BEGIN
+    SELECT CASE
+        WHEN ((SELECT order_form.id FROM order_form WHERE order_form.id=old.id_order_form AND order_form.status='open') IS NULL)
+        THEN RAISE(ABORT, 'try to update element in not opened order form')
+    END;
+END;
+
+/*
+ * Gestion du workflow sur un élément de commande: il doit être impossible de rajouter un élément de commande si la commande n'est pas ouverte
+ */
+CREATE TRIGGER order_element_insert_management_when_closed BEFORE INSERT ON order_element
+BEGIN
+    SELECT CASE
+        WHEN ((SELECT order_form.id FROM order_form WHERE order_form.id=new.id_order_form AND order_form.status='open') IS NULL)
+        THEN RAISE(ABORT, 'try to insert element in not opened order form')
+    END;
+END;
+
+/*
+ * Gestion du contraintes sur un élément de commande: un utilisateur ne faisant pas partie des contacts du propriétaire de la gallerie concernée par la commande ne doit pas pouvoir créer un élément de commande.
+ */
+CREATE TRIGGER order_element_insert_management_check_user_is_authored BEFORE INSERT ON order_element
+BEGIN
+    SELECT CASE
+        WHEN (
+            (
+                SELECT contact.id_user_contact
+                FROM contact
+                JOIN gallery ON gallery.id_user=contact.id_user_owner
+                JOIN order_form ON order_form.id_gallery=gallery.id
+                WHERE (contact.id_user_contact=new.id_user OR contact.id_user_owner=new.id_user)
+                AND order_form.id=new.id_order_form
+            ) IS NULL
+        )
+        THEN RAISE(ABORT, 'unauthorized user is ordering')
+    END;
+END;
+
diff --git a/module/Galerie/Module.php b/module/Galerie/Module.php
new file mode 100644 (file)
index 0000000..32cd7ae
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+
+namespace Galerie;
+
+use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
+use Zend\ModuleManager\Feature\ConfigProviderInterface;
+use Zend\ModuleManager\Feature\BootstrapListenerInterface;
+use Zend\ModuleManager\Feature\ServiceProviderInterface;
+
+
+use Zend\EventManager\EventInterface;
+use Zend\Mvc\ModuleRouteListener;
+
+
+use Galerie\Model\GalerieTable;
+use Galerie\Model\GalerieInfoTable;
+use Galerie\Form\GalerieForm;
+
+
+class Module implements
+    AutoloaderProviderInterface,
+    ConfigProviderInterface,
+    BootstrapListenerInterface,
+    ServiceProviderInterface
+{
+
+    public function getAutoloaderConfig() 
+    { 
+        return array( 
+            'Zend\Loader\ClassMapAutoloader' => array( 
+                __DIR__ . '/autoload_classmap.php', 
+            ), 
+            'Zend\Loader\StandardAutoloader' => array( 
+                'namespaces' => array( 
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, 
+                ), 
+            ), 
+        ); 
+    }
+
+    public function getConfig()
+    {
+        return include __DIR__ . '/config/module.config.php';
+    }
+
+    public function onBootstrap(EventInterface $e)
+    {
+        $translator = $e->getApplication()->getServiceManager()->get('translator');
+        \Zend\Validator\AbstractValidator::setDefaultTranslator($translator, 'val');
+    }
+
+    public function getServiceConfig()
+    {
+        return array(
+            'factories' => array(
+                'Galerie\Model\GalerieTable' => function($sm) {
+                    return new GalerieTable(
+                        $sm->get('Zend\Db\Adapter\Adapter')
+                    );
+                },
+                'Galerie\Model\GalerieInfoTable' => function($sm) {
+                    return new GalerieInfoTable(
+                        $sm->get('Zend\Db\Adapter\Adapter')
+                    );
+                },
+                'Galerie\Form\GalerieForm' => function($sm) {
+                    $result = new GalerieForm;
+                    $result->setTranslator($sm->get('translator'), 'galerie');
+                    $result->initialize();
+                    return $result;
+                },
+            ),
+        );
+    }
+}
diff --git a/module/Galerie/autoload_classmap.php b/module/Galerie/autoload_classmap.php
new file mode 100644 (file)
index 0000000..7f2deab
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+
+return array(
+    'Galerie\Controller\IndexController' =>
+        __DIR__ . '/src/Galerie/Controller/IndexController.php',
+);
diff --git a/module/Galerie/config/module.config.php b/module/Galerie/config/module.config.php
new file mode 100644 (file)
index 0000000..830cf49
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+
+return array(
+    'controllers' => array(
+        'invokables' => array(
+            'Galerie\Controller\Index' =>
+                'Galerie\Controller\IndexController'
+        ),
+    ),
+    'view_manager' => array(
+        'template_map' => array( 
+            'galerie/index/index' =>
+                       __DIR__ . '/../view/galerie/index/index.phtml', 
+            'galerie/index/edit' =>
+                       __DIR__ . '/../view/galerie/index/edit.phtml', 
+            'galerie/index/del' =>
+                       __DIR__ . '/../view/galerie/index/del.phtml', 
+            'galerie/index/view' =>
+                       __DIR__ . '/../view/galerie/index/view.phtml', 
+        ), 
+        'template_path_stack' => array(
+            'galerie' => __DIR__ . '/../view',
+        ),
+    ),
+    'router' => array(
+        'routes' => array(
+            'galerie' => array(
+                'type'    => 'Literal',
+                'options' => array(
+                    'route'    => '/galeries',
+                    'defaults' => array(
+                        '__NAMESPACE__' => 'Galerie\Controller',
+                        'controller'    => 'Index',
+                        'action'        => 'index',
+                    ),
+                ),
+                'verb' => 'get',
+                'may_terminate' => true,
+                'child_routes' => array(
+
+                    'add' => array(
+                        'type'    => 'Literal',
+                        'options' => array(
+                            'route'    => '/ajout',
+                            'defaults' => array(
+                                'action' => 'edit',
+                            ),
+                        ),
+                        'verb' => 'get,post',
+                    ),
+                    'edit' => array(
+                        'type'    => 'Segment',
+                        'options' => array(
+                            'route'    => '/editer/:id',
+                            'constraints' => array(
+                                'id' => '[1-9][0-9]*',
+                            ),
+                            'defaults' => array(
+                                'action' => 'edit',
+                            ),
+                        ),
+                        'verb' => 'get,post',
+                    ),
+                    'del' => array(
+                        'type'    => 'Segment',
+                        'options' => array(
+                            'route'    => '/supprimer/:id',
+                            'constraints' => array(
+                                'id' => '[1-9][0-9]*',
+                            ),
+                            'defaults' => array(
+                                'action' => 'del',
+                            ),
+                        ),
+                        'verb' => 'get,post',
+                    ),
+                    'view' => array(
+                        'type'    => 'Segment',
+                        'options' => array(
+                            'route'    => '/voir/:id',
+                            'constraints' => array(
+                                'id' => '[1-9][0-9]*',
+                            ),
+                            'defaults' => array(
+                                'action' => 'view',
+                            ),
+                        ),
+                    ),
+                    'add_or_edit' => array(
+                        'type'    => 'Segment',
+                        'options' => array(
+                            'route'    => '/ajouter_editer/[:id]',
+                            'constraints' => array(
+                                'id' => '[1-9][0-9]*',
+                            ),
+                            'defaults' => array(
+                                'action' => 'edit',
+                                'id' => null,
+                            ),
+                        ),
+                        'verb' => 'get,post',
+                    ),
+                    'default' => array(
+                        'type'    => 'Segment',
+                        'options' => array(
+                            'route'    => '/[:controller[/:action]]',
+                            'constraints' => array(
+                                'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
+                                'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
+                            ),
+                            'defaults' => array(
+                            ),
+                        ),
+                    ),
+                ),
+            ),
+        ),
+    ),
+    'service_manager' => array( 
+        'factories' => array( 
+            'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory', 
+        ), 
+    ), 
+    'translator' => array( 
+        'locale' => 'fr_FR', 
+        'translation_file_patterns' => array( 
+            array( 
+                'type'     => 'gettext', 
+                'base_dir' => __DIR__ . '/../language', 
+                'pattern'  => '%s.mo', 
+                'text_domain'  => 'galerie', 
+            ), 
+            array( 
+                'type'     => 'phpArray', 
+                'base_dir' => __DIR__ . '/../language/val', 
+                'pattern'  => 'Zend_Validate_%s.php', 
+                'text_domain'  => 'val', 
+            ), 
+        ), 
+    ), 
+);
diff --git a/module/Galerie/language/fr_FR.mo b/module/Galerie/language/fr_FR.mo
new file mode 100644 (file)
index 0000000..8f8ff36
Binary files /dev/null and b/module/Galerie/language/fr_FR.mo differ
diff --git a/module/Galerie/language/fr_FR.po b/module/Galerie/language/fr_FR.po
new file mode 100644 (file)
index 0000000..e624bf3
--- /dev/null
@@ -0,0 +1,75 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Projet galerie, Module galerie\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-11-15 16:43+0100\n"
+"PO-Revision-Date: 2012-11-15 16:43+0100\n"
+"Last-Translator: Sébastien CHAZALLET <s.chazallet@gmail.com>\n"
+"Language-Team: \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-KeywordsList: _;gettext;gettext_noop;translate\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: /var/git/zf2biz/galerie/module/Galerie\n"
+"X-Poedit-SearchPath-1: .\n"
+
+#: /var/git/zf2biz/galerie/module/Galerie/src/Galerie/Form/GalerieForm.php:34
+msgid "Galerie_form_label_name"
+msgstr "Nom de la galerie"
+
+#: /var/git/zf2biz/galerie/module/Galerie/src/Galerie/Form/GalerieForm.php:43
+msgid "Galerie_form_label_description"
+msgstr "Description de la galerie"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:1
+msgid "Galerie_index_title"
+msgstr "Liste des galeries"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:6
+msgid "Galerie_index_table_name"
+msgstr "Nom de la galerie"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:7
+msgid "Galerie_index_table_description"
+msgstr "Description"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:10
+msgid "Galerie_index_table_username"
+msgstr "Propriétaire"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:13
+msgid "Galerie_index_table_nb"
+msgstr "Nombre"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:16
+msgid "Galerie_index_table_actions"
+msgstr "Actions"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:22
+msgid "Galerie_index_table_void"
+msgstr "Il n'y a aucune galeries pour le moment"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:39
+msgid "Galerie_index_table_lien_view"
+msgstr "Voir"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:40
+msgid "Galerie_index_table_lien_edit"
+msgstr "Éditer"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/index.phtml:41
+msgid "Galerie_index_table_lien_del"
+msgstr "Supprimer"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/edit.phtml:2
+msgid "Galerie_add_title"
+msgstr "Ajouter une galerie"
+
+#: /var/git/zf2biz/galerie/module/Galerie/view/galerie/index/edit.phtml:4
+msgid "Galerie_edit_title"
+msgstr "Modifier une galerie"
+
+#~ msgid "index"
+#~ msgstr "Page d'accueil galerie/back-office"
diff --git a/module/Galerie/language/val/Zend_Validate_fr_FR.php b/module/Galerie/language/val/Zend_Validate_fr_FR.php
new file mode 100644 (file)
index 0000000..9a041c5
--- /dev/null
@@ -0,0 +1,280 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Translator
+ * @subpackage Resource
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * FR-Revision: 09.Sept.2012
+ */
+return array(
+    // Zend_I18n_Validator_Alnum
+    "Invalid type given. String, integer or float expected" => "Type invalide. Chaîne, entier ou flottant attendu",
+    "The input contains characters which are non alphabetic and no digits" => "L'entrée contient des caractères non alphabétiques et non numériques",
+    "The input is an empty string" => "L'entrée est une chaîne vide",
+
+    // Zend_I18n_Validator_Alpha
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input contains non alphabetic characters" => "L'entrée contient des caractères non alphabétiques",
+    "The input is an empty string" => "L'entrée est une chaîne vide",
+
+    // Zend_I18n_Validator_Float
+    "Invalid type given. String, integer or float expected" => "Type invalide. Chaîne, entier ou flottant attendu",
+    "The input does not appear to be a float" => "L'entrée n'est pas un nombre flottant",
+
+    // Zend_I18n_Validator_Int
+    "Invalid type given. String or integer expected" => "Type invalide. Chaîne ou entier attendu",
+    "The input does not appear to be an integer" => "L'entrée n'est pas un entier",
+
+    // Zend_I18n_Validator_PostCode
+    "Invalid type given. String or integer expected" => "Type invalid. Chaîne ou entier attendu",
+    "The input does not appear to be a postal code" => "L'entrée ne semble pas être un code postal valide",
+    "An exception has been raised while validating the input" => "Une exception a été levée lors de la validation de l'entrée",
+
+    // Zend_Validator_Barcode
+    "The input failed checksum validation" => "L'entrée n'a pas passé la validation de la somme de contrôle",
+    "The input contains invalid characters" => "L'entrée contient des caractères invalides",
+    "The input should have a length of %length% characters" => "L'entrée devrait contenir %length% caractères",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+
+    // Zend_Validator_Between
+    "The input is not between '%min%' and '%max%', inclusively" => "L'entrée n'est pas comprise entre '%min%' et '%max%', inclusivement",
+    "The input is not strictly between '%min%' and '%max%'" => "L'entrée n'est pas strictement comprise entre '%min%' et '%max%'",
+
+    // Zend_Validator_Callback
+    "The input is not valid" => "L'entrée n'est pas valide",
+    "An exception has been raised within the callback" => "Une exception a été levée dans la fonction de rappel",
+
+    // Zend_Validator_CreditCard
+    "The input seems to contain an invalid checksum" => "L'entrée semble contenir une somme de contrôle invalide",
+    "The input must contain only digits" => "L'entrée ne doit contenir que des chiffres",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input contains an invalid amount of digits" => "L'entrée contient un nombre invalide de chiffres",
+    "The input is not from an allowed institute" => "L'entrée ne provient pas d'une institution autorisée",
+    "The input seems to be an invalid creditcard number" => "L'entrée semble être un numéro de carte bancaire invalide",
+    "An exception has been raised while validating the input" => "Une exception a été levée lors de la validation de l'entrée",
+
+    // Zend_Validator_Csrf
+    "The form submitted did not originate from the expected site" => "Le formulaire ne provient pas du site attendu",
+
+    // Zend_Validator_Date
+    "Invalid type given. String, integer, array or DateTime expected" => "Type invalide. Chaîne, entier, tableau ou DateTime attendu",
+    "The input does not appear to be a valid date" => "L'entrée ne semble pas être une date valide",
+    "The input does not fit the date format '%format%'" => "L'entrée ne correspond pas au format '%format%'",
+
+    // Zend_Validator_DateStep
+    "Invalid type given. String, integer, array or DateTime expected" => "Entrée invalide. Chaîne, entier, tableau ou DateTime attendu",
+    "The input does not appear to be a valid date" => "L'entrée ne semble pas être une date valide",
+    "The input is not a valid step" => "L'entrée n'est pas un intervalle valide",
+
+    // Zend_Validator_Db_AbstractDb
+    "No record matching the input was found" => "Aucun enregistrement trouvé",
+    "A record matching the input was found" => "Un enregistrement a été trouvé",
+
+    // Zend_Validator_Digits
+    "The input must contain only digits" => "L'entrée ne doit contenir que des chiffres",
+    "The input is an empty string" => "L'entrée est une chaîne vide",
+    "Invalid type given. String, integer or float expected" => "Type invalide. Chaîne, entier ou flottant attendu",
+
+    // Zend_Validator_EmailAddress
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input is not a valid email address. Use the basic format local-part@hostname" => "L'entrée n'est pas une adresse email valide. Utilisez le format local-part@hostname",
+    "'%hostname%' is not a valid hostname for the email address" => "'%hostname%' n'est pas un nom d'hôte valide pour l'adresse email",
+    "'%hostname%' does not appear to have any valid MX or A records for the email address" => "'%hostname%' ne semble pas avoir d'enregistrement MX valide pour l'adresse email",
+    "'%hostname%' is not in a routable network segment. The email address should not be resolved from public network" => "'%hostname%' n'est pas dans un segment réseau routable. L'adresse email ne devrait pas être résolue depuis un réseau public.",
+    "'%localPart%' can not be matched against dot-atom format" => "'%localPart%' ne correspond pas au format dot-atom",
+    "'%localPart%' can not be matched against quoted-string format" => "'%localPart%' ne correspond pas à une chaîne entre quotes",
+    "'%localPart%' is not a valid local part for the email address" => "'%localPart%' n'est pas une partie locale valide pour l'adresse email",
+    "The input exceeds the allowed length" => "L'entrée dépasse la taille autorisée",
+
+    // Zend_Validator_Explode
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+
+    // Zend_Validator_File_Count
+    "Too many files, maximum '%max%' are allowed but '%count%' are given" => "Trop de fichiers. '%max%' sont autorisés au maximum, mais '%count%' reçu(s)",
+    "Too few files, minimum '%min%' are expected but '%count%' are given" => "Trop peu de fichiers. '%min%' sont attendus, mais '%count%' reçu(s)",
+
+    // Zend_Validator_File_Crc32
+    "File '%value%' does not match the given crc32 hashes" => "Le fichier '%value%' ne correspond pas aux sommes de contrôle CRC32 données",
+    "A crc32 hash could not be evaluated for the given file" => "Une somme de contrôle CRC32 n'a pas pu être calculée pour le fichier",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_ExcludeExtension
+    "File '%value%' has a false extension" => "Le fichier '%value%' a une mauvaise extension",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_Exists
+    "File '%value%' does not exist" => "Le fichier '%value%' n'existe pas",
+
+    // Zend_Validator_File_Extension
+    "File '%value%' has a false extension" => "Le fichier '%value%' a une mauvaise extension",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_FilesSize
+    "All files in sum should have a maximum size of '%max%' but '%size%' were detected" => "Tous les fichiers devraient avoir une taille maximale de '%max%' mais une taille de '%size%' a été détectée",
+    "All files in sum should have a minimum size of '%min%' but '%size%' were detected" => "Tous les fichiers devraient avoir une taille minimale de '%max%' mais une taille de '%size%' a été détectée",
+    "One or more files can not be read" => "Un ou plusieurs fichiers ne peut pas être lu",
+
+    // Zend_Validator_File_Hash
+    "File '%value%' does not match the given hashes" => "Le fichier '%value%' ne correspond pas aux sommes de contrôle données",
+    "A hash could not be evaluated for the given file" => "Une somme de contrôle n'a pas pu être calculée pour le fichier",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_ImageSize
+    "Maximum allowed width for image '%value%' should be '%maxwidth%' but '%width%' detected" => "La largeur maximale pour l'image '%value%' devrait être '%maxwidth%', mais '%width%' détecté",
+    "Minimum expected width for image '%value%' should be '%minwidth%' but '%width%' detected" => "La largeur minimale pour l'image '%value%' devrait être '%minwidth%', mais '%width%' détecté",
+    "Maximum allowed height for image '%value%' should be '%maxheight%' but '%height%' detected" => "La hauteur maximale pour l'image '%value%' devrait être '%maxheight%', mais '%height%' détecté",
+    "Minimum expected height for image '%value%' should be '%minheight%' but '%height%' detected" => "La hauteur maximale pour l'image '%value%' devrait être '%minheight%', mais '%height%' détecté",
+    "The size of image '%value%' could not be detected" => "La taille de l'image '%value%' n'a pas pu être détectée",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_IsCompressed
+    "File '%value%' is not compressed, '%type%' detected" => "Le fichier '%value%' n'est pas compressé, '%type%' détecté",
+    "The mimetype of file '%value%' could not be detected" => "Le type MIME du fichier '%value%' n'a pas pu être détecté",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_IsImage
+    "File '%value%' is no image, '%type%' detected" => "Le fichier '%value%' n'est pas une image, '%type%' détecté",
+    "The mimetype of file '%value%' could not be detected" => "Le type MIME du fichier '%value%' n'a pas pu être détecté",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_Md5
+    "File '%value%' does not match the given md5 hashes" => "Le fichier '%value%' ne correspond pas aux sommes de contrôle MD5 données",
+    "A md5 hash could not be evaluated for the given file" => "Une somme de contrôle MD5 n'a pas pu être calculée pour le fichier",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_MimeType
+    "File '%value%' has a false mimetype of '%type%'" => "Le fichier '%value%' a un faux type MIME : '%type%'",
+    "The mimetype of file '%value%' could not be detected" => "Le type MIME du fichier '%value%' n'a pas pu être détecté",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_NotExists
+    "File '%value%' exists" => "Le fichier '%value%' existe",
+
+    // Zend_Validator_File_Sha1
+    "File '%value%' does not match the given sha1 hashes" => "Le fichier '%value%' ne correspond pas aux sommes de contrôle SHA1 données",
+    "A sha1 hash could not be evaluated for the given file" => "Une somme de contrôle SHA1 n'a pas pu être calculée pour le fichier",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_Size
+    "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected" => "La taille de fichier maximale pour '%value%' est '%max%', mais '%size%' détectée",
+    "Minimum expected size for file '%value%' is '%min%' but '%size%' detected" => "La taille de fichier minimale pour '%value%' est '%min%', mais '%size%' détectée",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_File_Upload
+    "File '%value%' exceeds the defined ini size" => "Le fichier '%value%' dépasse la taille définie dans le fichier INI",
+    "File '%value%' exceeds the defined form size" => "Le fichier '%value%' dépasse la taille définie dans le formulaire",
+    "File '%value%' was only partially uploaded" => "Le fichier '%value%' n'a été que partiellement envoyé",
+    "File '%value%' was not uploaded" => "Le fichier '%value%' n'a pas été envoyé",
+    "No temporary directory was found for file '%value%'" => "Le dossier temporaire n'a pas été trouvé pour le fichier '%value%'",
+    "File '%value%' can't be written" => "Impossible d'écrire dans le fichier '%value%'",
+    "A PHP extension returned an error while uploading the file '%value%'" => "Une extension PHP a retourné une erreur en envoyant le fichier '%value%'",
+    "File '%value%' was illegally uploaded. This could be a possible attack" => "Le fichier '%value%' a été envoyé illégalement. Il peut s'agir d'une attaque",
+    "File '%value%' was not found" => "Le fichier '%value%' n'a pas été trouvé",
+    "Unknown error while uploading file '%value%'" => "Erreur inconnue lors de l'envoi du fichier '%value%'",
+
+    // Zend_Validator_File_WordCount
+    "Too much words, maximum '%max%' are allowed but '%count%' were counted" => "Trop de mots. '%max%' sont autorisés, '%count%' comptés",
+    "Too less words, minimum '%min%' are expected but '%count%' were counted" => "Pas assez de mots. '%min%' sont attendus, '%count%' comptés",
+    "File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
+
+    // Zend_Validator_GreaterThan
+    "The input is not greater than '%min%'" => "L'entrée n'est pas supérieure à '%min%'",
+    "The input is not greater or equal than '%min%'" => "L'entrée n'est pas supérieure ou égale à '%min%'",
+
+    // Zend_Validator_Hex
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input contains non-hexadecimal characters" => "L'entrée contient des caractères non-hexadécimaux",
+
+    // Zend_Validator_Hostname
+    "The input appears to be a DNS hostname but the given punycode notation cannot be decoded" => "L'entrée semble être un DNS valide mais le code n'a pu être décodé",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input appears to be a DNS hostname but contains a dash in an invalid position" => "L'entrée semble être un nom d'hôte DNS mais il contient un tiret à une position invalide",
+    "The input does not match the expected structure for a DNS hostname" => "L'entrée ne correspond pas à la structure attendue d'un nom d'hôte DNS",
+    "The input appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'" => "L'entrée semble être un nom d'hôte DNS valide mais ne correspond pas au schéma de l'extension TLD '%tld%'",
+    "The input does not appear to be a valid local network name" => "L'entrée ne semble pas être un nom de réseau local valide",
+    "The input does not appear to be a valid URI hostname" => "L'entrée ne semble pas être une URI de nom d'hôte valide",
+    "The input appears to be an IP address, but IP addresses are not allowed" => "L'entrée semble être une adresse IP valide, mais les adresses IP ne sont pas autorisées",
+    "The input appears to be a local network name but local network names are not allowed" => "L'entrée semble être un nom de réseau local, mais les réseaux locaux ne sont pas autorisés",
+    "The input appears to be a DNS hostname but cannot extract TLD part" => "L'entrée semble être un nom d'hôte DNS mais l'extension TLD ne peut être extraite",
+    "The input appears to be a DNS hostname but cannot match TLD against known list" => "L'entrée semble être un nom d'hôte DNS mais son extension TLD semble inconnue",
+
+    // Zend_Validator_Iban
+    "Unknown country within the IBAN" => "Pays inconnu pour l'IBAN",
+    "Countries outside the Single Euro Payments Area (SEPA) are not supported" => "Les pays en dehors du Single Euro Payments Area (SEPA) ne sont pas supportés",
+    "The input has a false IBAN format" => "L'entrée n'a pas un format IBAN valide",
+    "The input has failed the IBAN check" => "L'entrée n'a pas passé la validation IBAN",
+
+    // Zend_Validator_Identical
+    "The two given tokens do not match" => "Les deux jetons passés ne correspondent pas",
+    "No token was provided to match against" => "Aucun jeton de correspondance n'a été donné",
+
+    // Zend_Validator_InArray
+    "The input was not found in the haystack" => "L'entrée ne fait pas partie des valeurs attendues",
+
+    // Zend_Validator_Ip
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input does not appear to be a valid IP address" => "L'entrée ne semble pas être une adresse IP valide",
+
+    // Zend_Validator_Isbn
+    "Invalid type given. String or integer expected" => "Type invalide. Chaîne ou entier attendu",
+    "The input is not a valid ISBN number" => "L'entrée n'est pas un nombre ISBN valide",
+
+    // Zend_Validator_LessThan
+    "The input is not less than '%max%'" => "L'entrée n'est pas inférieure à '%max%'",
+    "The input is not less or equal than '%max%'" => "L'entrée n'est pas inférieure ou égale à '%max%'",
+
+    // Zend_Validator_NotEmpty
+    "Value is required and can't be empty" => "Une valeur est requise et ne peut être vide",
+    "Invalid type given. String, integer, float, boolean or array expected" => "Type invalide. Chaîne, entier, flottant, booléen ou tableau attendu",
+
+    // Zend_Validator_Regex
+    "Invalid type given. String, integer or float expected" => "Type invalide. Chaîne, entier ou flottant attendu",
+    "The input does not match against pattern '%pattern%'" => "L'entrée n'est pas valide avec l'expression '%pattern%'",
+    "There was an internal error while using the pattern '%pattern%'" => "Une erreur interne est survenue avec l'expression '%pattern%'",
+
+    // Zend_Validator_Sitemap_Changefreq
+    "The input is not a valid sitemap changefreq" => "L'entrée n'est pas une valeur de fréquence de changement de sitemap valide",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+
+    // Zend_Validator_Sitemap_Lastmod
+    "The input is not a valid sitemap lastmod" => "L'entrée n'est pas une date de dernière modification de sitemap valide",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+
+    // Zend_Validator_Sitemap_Loc
+    "The input is not a valid sitemap location" => "L'entrée n'est pas un emplacement de sitemap valide",
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+
+    // Zend_Validator_Sitemap_Priority
+    "The input is not a valid sitemap priority" => "L'entrée n'est pas une priorité de sitemap valide",
+    "Invalid type given. Numeric string, integer or float expected" => "Type invalide. Chaîne numérique, entier ou flottant attendu",
+
+    // Zend_Validator_Step
+    "Invalid value given. Scalar expected" => "Type invalide. Scalaire attendu",
+    "The input is not a valid step" => "L'entrée n'est pas un intervalle valide",
+
+    // Zend_Validator_StringLength
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input is less than %min% characters long" => "L'entrée contient moins de %min% caractères",
+    "The input is more than %max% characters long" => "L'entrée contient plus de %max% caractères",
+
+    // Zend_Validator_Uri
+    "Invalid type given. String expected" => "Type invalide. Chaîne attendue",
+    "The input does not appear to be a valid Uri" => "L'entrée ne semble pas être une URI valide",
+);
diff --git a/module/Galerie/src/Galerie/Controller/IndexController.php b/module/Galerie/src/Galerie/Controller/IndexController.php
new file mode 100644 (file)
index 0000000..0219600
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+
+namespace Galerie\Controller; 
+
+use Zend\Mvc\Controller\AbstractActionController; 
+use Zend\View\Model\ViewModel;
+
+use Galerie\Model\Galerie;
+
+class IndexController extends AbstractActionController 
+{
+
+    private $_galerieTable;
+    private $_galerieInfoTable;
+    private $_galerieForm;
+
+    private $_translator;
+
+
+    private function _getGalerieTable()
+    {
+        if (!$this->_galerieTable) {
+            $sm = $this->getServiceLocator();
+            $this->_galerieTable = $sm->get('Galerie\Model\GalerieTable');
+        }
+        return $this->_galerieTable;
+    }
+
+    private function _getGalerieInfoTable()
+    {
+        if (!$this->_galerieInfoTable) {
+            $sm = $this->getServiceLocator();
+            $this->_galerieInfoTable = $sm->get('Galerie\Model\GalerieInfoTable');
+        }
+        return $this->_galerieInfoTable;
+    }
+
+    private function _getTranslator()
+    {
+        if (!$this->_translator) {
+            $sm = $this->getServiceLocator();
+            $this->_translator = $sm->get('translator');
+        }
+        return $this->_translator;
+    }
+
+    private function _getGalerieForm()
+    {
+        if (!$this->_galerieForm) {
+            $sm = $this->getServiceLocator();
+            $this->_galerieForm = $sm->get('Galerie\Form\GalerieForm');
+        }
+        return $this->_galerieForm;
+    }
+
+
+
+    public function indexAction() 
+    { 
+        return new ViewModel(array(
+            'galeries' => $this->_getGalerieInfoTable()->all(),
+        )); 
+    } 
+
+    public function editAction() 
+    {
+        // Création du formulaire
+        $form = $this->_getGalerieForm();
+
+        // Récupération de l'objet de travail
+        $id = $this->params()->fromRoute('id', null);
+        if (!$id) {
+            $galerie = null;
+        } else {
+            $galerie = $this->_getGalerieTable()->any(array('id' => $id));
+        }
+
+        // Sommes-nous en ajout ou en édition ?
+        if (!$galerie) {
+            // Nous sommes en ajout
+            $form->get('submit')->setValue('Ajouter');
+            // Il faut créer un nouveau objet Galerie
+            $galerie = new Galerie;
+            // Garder cette information pour la vue
+            $is_new = true;
+        } else {
+            // Nous sommes en modification
+            $form->get('submit')->setValue('Modifier');
+            // Il faut préremplir le formulaire avec les données actuelles
+            $form->bind($galerie);
+            // Garder cette information pour la vue
+            $is_new = false;
+        }
+
+        // Récupération de l'objet requête
+        $request = $this->getRequest();
+        if ($request->isPost()) {
+            // Mise en place pour la validation du formulaire
+            $form->setInputFilter($galerie->getInputFilter());
+            $form->setData($request->getPost());
+
+            // Validation des données
+            if ($form->isValid()) {
+                // Sauvegarde des données
+                $galerie = $form->getData();
+                if ($is_new) {
+                    // Si l'objet n'est pas nouveau, les autres paramètres restent inchangés
+                    // Si l'objet est nouveau, il faut renseigner l'id de l'utilisateur courant
+                    $galerie->id_user = 1; //TODO: Mettre ici le user connecté
+                }
+                $this->_getGalerieTable()->save($galerie);
+
+                // Redirection 
+                return $this->redirect()->toRoute('galerie');
+            }
+        }
+
+        // On prépare l'affichage du formulaire
+        if ($is_new) {
+            $form->setAttribute('action', $this->url()->fromRoute('galerie/add'));
+        } else {
+            $form->setAttribute('action', $this->url()->fromRoute('galerie/edit', array('id' => $id)));
+        }
+        $form->prepare();
+
+        // On passe la main à la vue
+        return new ViewModel(array(
+            'id' => $id,
+            'form' => $form,
+            'is_new' => $is_new,
+        ));
+    } 
+
+    public function delAction() 
+    { 
+        return $this->redirect()->toRoute('galerie/view', array(
+            'id' => $this->params()->fromRoute('id', null),
+        ));
+    } 
+
+    public function viewAction() 
+    {
+        $id = $this->params()->fromRoute('id', null);
+        $galerie = $this->_getGalerieInfoTable()->any($id);
+        return new ViewModel(array(
+            'id' => $id,
+            'galerie' => $galerie,
+        ));
+    } 
+
+} 
diff --git a/module/Galerie/src/Galerie/Form/GalerieForm.php b/module/Galerie/src/Galerie/Form/GalerieForm.php
new file mode 100644 (file)
index 0000000..4e3749b
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+
+namespace Galerie\Form;
+
+use Zend\Form\Form;
+
+use Zend\I18n\Translator\TranslatorAwareInterface;
+use Zend\I18n\Translator\Translator;
+
+
+class GalerieForm extends Form implements TranslatorAwareInterface
+{
+
+    private $_translator;
+    private $_textDomain = 'galerie';
+    private $_translator_enabled = true; 
+
+
+    public function initialize()
+    {
+        $this->setAttribute('method', 'post');
+        $this->add(array(
+            'name' => 'id',
+            'attributes' => array(
+                'type' => 'hidden',
+            ),
+        ));
+        $this->add(array(
+            'name' => 'name',
+            'attributes' => array(
+                'type' => 'text',
+            ),
+            'options' => array(
+                'label' => $this->translate('Galerie_form_label_name'),
+            )
+        ));
+        $this->add(array(
+            'name' => 'description',
+            'attributes' => array(
+                'type' => 'text',
+            ),
+            'options' => array(
+                'label' => $this->translate('Galerie_form_label_description'),
+            )
+        ));
+        $this->add(array(
+            'name' => 'submit',
+            'attributes' => array(
+                'type' => 'submit',
+                'value' => 'Valider',
+                'id' => 'submit_galerie_form',
+            ),
+        ));
+    }
+
+
+
+
+    public function translate($k)
+    {
+        if ($this->_translator && $this->_translator_enabled) {
+            return $this->_translator->translate($k, $this->_textDomain);
+        }
+        return $k . '(Non traduit)';
+    }
+
+
+    public function setTranslator(Translator $translator = null, $textDomain = null)
+    {
+        $this->_translator = $translator;
+       $this->_textDomain = $textDomain;
+    }
+
+    public function getTranslator()
+    {
+        return $this->_translator;
+    }
+
+    public function hasTranslator()
+    {
+        return $this->_translator !== null;
+    }
+
+    public function setTranslatorEnabled($enabled = true)
+    {
+        $this->_translator_enabled = $enabed;
+    }
+
+    public function isTranslatorEnabled()
+    {
+        return $this->_translator_enabled;
+    }
+
+    public function setTranslatorTextDomain($textDomain = 'default')
+    {
+       $this->_textDomain = $textDomain;
+    }
+
+    public function getTranslatorTextDomain()
+    {
+        return $this->_textDomain;
+    }
+
+}
diff --git a/module/Galerie/src/Galerie/Model/Galerie.php b/module/Galerie/src/Galerie/Model/Galerie.php
new file mode 100644 (file)
index 0000000..6b46e20
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+
+namespace Galerie\Model;
+
+use Zend\InputFilter\Factory as InputFactory;
+use Zend\InputFilter\InputFilter;
+use Zend\InputFilter\InputFilterInterface;
+use Zend\InputFilter\InputFilterAwareInterface;
+
+use Custom\Model\Entity;
+
+class Galerie extends Entity implements InputFilterAwareInterface
+{
+    public $id;
+    public $id_user;
+    public $name;
+    public $description;
+    public $created;
+    public $updated;
+
+    protected $inputFilter;
+
+
+    protected $columns = array(
+        'id',
+        'id_user',
+        'name',
+        'description',
+        'created',
+        'updated',
+    );
+
+    protected $updatable_columns = array(
+        'id_user',
+        'name',
+        'description',
+    );
+
+    protected $primary_columns = array(
+        'id',
+    );
+
+    public function getArrayCopy()
+    {
+        return $this->toArray();
+    }
+
+    public function setInputFilter(InputFilterInterface $inputfilter)
+    {
+        throw new \Exception("This entity does not allow to set Input Filter");
+    }
+
+    public function getInputFilter()
+    {
+        if (!$this->inputFilter) {
+            $inputFilter = new InputFilter;
+            $factory = new InputFactory;
+
+            $inputFilter->add($factory->createInput(array(
+                'name' => 'id',
+                'required' => true,
+                'filters' => array(
+                    array('name' => 'Int'),
+                ),
+            )));
+
+            $inputFilter->add($factory->createInput(array(
+                'name' => 'name',
+                'required' => true,
+                'filters' => array(
+                    array('name' => 'StripTags'),
+                    array('name' => 'StringTrim'),
+                ),
+                'validators' => array(
+                    array(
+                        'name' => 'StringLength',
+                        'options' => array(
+                            'encoding' => 'UTF-8',
+                            'min' => 1,
+                            'max' => 32,
+                        ),
+                    ),
+                ),
+            )));
+
+            $inputFilter->add($factory->createInput(array(
+                'name' => 'description',
+                'required' => true,
+                'filters' => array(
+                    array('name' => 'StripTags'),
+                    array('name' => 'StringTrim'),
+                ),
+            )));
+
+            $this->inputFilter = $inputFilter;
+        }
+
+        return $this->inputFilter;
+
+    }
+
+}
diff --git a/module/Galerie/src/Galerie/Model/GalerieInfo.php b/module/Galerie/src/Galerie/Model/GalerieInfo.php
new file mode 100644 (file)
index 0000000..2abe6ca
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+namespace Galerie\Model;
+
+use Custom\Model\Entity;
+
+class GalerieInfo extends Entity
+{
+    public $id;
+    public $name;
+    public $description;
+    public $username;
+    public $nb;
+
+
+    protected $columns = array(
+        'id',
+        'name',
+        'description',
+        'username',
+        'nb',
+    );
+
+    protected $updatable_columns = array(
+    );
+
+    protected $primary_columns = array(
+    );
+
+}
diff --git a/module/Galerie/src/Galerie/Model/GalerieInfoTable.php b/module/Galerie/src/Galerie/Model/GalerieInfoTable.php
new file mode 100644 (file)
index 0000000..a0b3421
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+namespace Galerie\Model;
+
+use Zend\Db\Adapter\Adapter;
+use Zend\Db\ResultSet\ResultSet;
+use Zend\Db\TableGateway\TableGatewayInterface;
+use Zend\Db\Sql\Sql;
+
+use Custom\Model\Entity;
+
+class GalerieInfoTable implements TableGatewayInterface
+{
+
+    protected $adapter;
+    protected $resultSetPrototype;
+    protected $sql;
+
+    public function __construct(Adapter $adapter) {
+        // Gestion de l'adaptateur
+        if (!$adapter instanceof Adapter) {
+            throw new Exception\RuntimeException('GalerieInfoTable does not have an valid Adapter parameter');
+        }
+        $this->adapter = $adapter;
+
+        // Utilisation du patron de conception Prototype
+        // pour la création des objets ResultSet
+        $this->resultSetPrototype = new ResultSet();
+        $this->resultSetPrototype->setArrayObjectPrototype(
+            new GalerieInfo()
+        );
+
+        // Initialisation de l'outil de création de requête
+        $this->sql = new Sql($this->adapter, $this->getTable());
+    }
+
+
+    public function getTable()
+    {
+        return 'gallery'; // Table centrale de la requête
+    }
+
+
+    public function select($where = null)
+    {
+        $select = $this->sql->select()
+            ->columns(array('id', 'name', 'description'))
+            ->join('user', 'gallery.id_user = user.id', array(
+                'username' => new \Zend\Db\Sql\Expression("user.firstname || ' ' || user.lastname")
+            ))
+            ->join('photo', 'gallery.id = photo.id_gallery', array(
+                'nb' => new \Zend\Db\Sql\Expression('count(photo.id)')
+            ))
+            ->group(array(
+                'user.lastname',
+                'user.firstname',
+                'gallery.name'
+            ))
+            ->order(array(
+                'user.lastname',
+                'user.firstname',
+                'gallery.name'
+            ));
+        if ($where) {
+            $select->where($where);
+        }
+
+        // prepare and execute
+        $statement = $this->sql->prepareStatementForSqlObject($select);
+        $result = $statement->execute();
+
+        // build result set
+        $resultSet = clone $this->resultSetPrototype;
+        $resultSet->initialize($result);
+
+        return $resultSet;
+    }
+
+    public function insert($set) {
+        throw new \Exception('insert is not allowed');
+    }
+
+    public function update($set, $where = null) {
+        throw new \Exception('update is not allowed');
+    }
+
+    public function delete($where) {
+        throw new \Exception('delete is not allowed');
+    }
+
+    public function all()
+    {
+        return $this->select();
+    }
+
+    public function one($id)
+    {
+        if ($id === null) {
+            $row = null;
+        } else {
+            $row = $this->select(array('gallery.id' => (int) $id))->current();
+        }
+        if (!$row) {
+            throw new \Exception("cannot get row {id: {$id}} in table 'galerie'");
+        }
+        return $row;
+    }
+
+    public function any($id)
+    {
+        if ($id === null) {
+            $row = null;
+        } else {
+            $row = $this->select(array('gallery.id' => (int) $id))->current();
+        }
+        return $row;
+    }
+
+    public function all_by_user($id_user)
+    {
+        return $this->select(array('gallery.id_user' => (int) $id_user));
+    }
+
+}
diff --git a/module/Galerie/src/Galerie/Model/GalerieTable.php b/module/Galerie/src/Galerie/Model/GalerieTable.php
new file mode 100644 (file)
index 0000000..62ffc62
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+namespace Galerie\Model;
+
+use Zend\Db\Adapter\Adapter;
+use Custom\Model\Manager;
+use Custom\Model\Entity;
+
+class GalerieTable extends Manager
+{
+    public $table = 'gallery';
+
+    public function __construct(Adapter $adapter)
+    {
+        parent::__construct($adapter, new Galerie());
+    }
+
+    public function get($id)
+    {
+        return $this->one(array(
+            'id' => (int) $id
+        ));
+    }
+
+    protected function is_new(Entity $entity)
+    {
+        return $entity->id === null;
+    }
+
+    protected function extract_primary(Entity $entity)
+    {
+        return array(
+            'id' => (int) $entity->id
+        );
+    }
+
+    // La méthode save remplace saveGalerie
+
+    public function delete($id)
+    {
+        parent::delete(array(
+            'id' => (int) $id
+        ));
+    }
+
+
+    // Fonctionnalités supplémentaires
+
+    public function get_by_owner($id_user)
+    {
+        return $this->select(array(
+            'id_user' => (int) $id_user,
+        ));
+    }
+
+    public function delete_by_owner($id_user)
+    {
+        $this->delete(array(
+            'id_user' => (int) $id_user,
+        ));
+    }
+
+    public function get_by_name($name)
+    {
+        // la colonne 'name' est UNIQUE
+        return $this->one(array(
+            'name' => name,
+        ));
+    }
+
+    public function find_by_name($name)
+    {
+        // la colonne 'name' est UNIQUE
+        return $this->any(array(
+            'name' => name,
+        ));
+    }
+
+}
diff --git a/module/Galerie/view/galerie/index/del.phtml b/module/Galerie/view/galerie/index/del.phtml
new file mode 100644 (file)
index 0000000..049cf40
--- /dev/null
@@ -0,0 +1 @@
+<p>vue <em>back-office</em> d&rsquo;une <strong>galerie</strong>&nbsp;: del</p>
diff --git a/module/Galerie/view/galerie/index/edit.phtml b/module/Galerie/view/galerie/index/edit.phtml
new file mode 100644 (file)
index 0000000..4e5f7d2
--- /dev/null
@@ -0,0 +1,14 @@
+<?php if ($is_new): ?>
+<h1><?php echo $this->translate('Galerie_add_title', 'galerie'); ?></h1>
+<?php else: ?>
+<h1><?php echo $this->translate('Galerie_edit_title', 'galerie'); ?></h1>
+<?php endif; ?>
+
+<?php
+echo $this->form()->openTag($form);
+echo $this->formHidden($form->get('id'));
+echo $this->formRow($form->get('name'));
+echo $this->formRow($form->get('description'));
+echo $this->formSubmit($form->get('submit'));
+echo $this->form()->closeTag($form);
+?>
diff --git a/module/Galerie/view/galerie/index/index.phtml b/module/Galerie/view/galerie/index/index.phtml
new file mode 100644 (file)
index 0000000..f9d18c7
--- /dev/null
@@ -0,0 +1,46 @@
+<h1><?php echo $this->translate('Galerie_index_title', 'galerie'); ?></h1>
+
+<table id="galeries">
+       <tr>
+               <th>
+                       <strong><?php echo $this->translate('Galerie_index_table_name', 'galerie'); ?></strong>
+                       <em><?php echo $this->translate('Galerie_index_table_description', 'galerie'); ?></em>
+               </th>
+               <th>
+                       <?php echo $this->translate('Galerie_index_table_username', 'galerie'); ?>
+               </th>
+               <th>
+                       <?php echo $this->translate('Galerie_index_table_nb', 'galerie'); ?>
+               </th>
+               <th>
+                       <?php echo $this->translate('Galerie_index_table_actions', 'galerie'); ?>
+               </th>
+       </tr>
+       <?php if ($galeries->count() == 0): ?>
+       <tr>
+               <td colspan="5">
+                       <strong><?php echo $this->translate('Galerie_index_table_void', 'galerie'); ?></strong>
+               </td>
+       </tr>
+       <?php else: ?>
+       <?php foreach($galeries as $galerie): ?>
+       <tr>
+               <td>
+                       <strong><?php echo $this->escapeHtml($galerie->name); ?></strong>
+                       <em><?php echo $this->escapeHtml($galerie->description); ?></em>
+               </td>
+               <td>
+                       <?php echo $this->escapeHtml($galerie->username); ?>
+               </td>
+               <td>
+                       <?php echo $this->escapeHtml($galerie->nb); ?>
+               </td>
+               <td>
+                        <a href="<?php echo $this->url('galerie/view', array('id'=>$galerie->id)); ?>"><?php echo $this->translate('Galerie_index_table_lien_view', 'galerie'); ?></a>
+                        <a href="<?php echo $this->url('galerie/edit', array('id'=>$galerie->id)); ?>"><?php echo $this->translate('Galerie_index_table_lien_edit', 'galerie'); ?></a>
+                        <a href="<?php echo $this->url('galerie/del', array('id'=>$galerie->id)); ?>"><?php echo $this->translate('Galerie_index_table_lien_del', 'galerie'); ?></a>
+               </td>
+       </tr>
+       <?php endforeach; ?>
+       <?php endif; ?>
+</table>
diff --git a/module/Galerie/view/galerie/index/view.phtml b/module/Galerie/view/galerie/index/view.phtml
new file mode 100644 (file)
index 0000000..7b09f0c
--- /dev/null
@@ -0,0 +1,7 @@
+<p>vue <em>back-office</em> d&rsquo;une <strong>galerie</strong>&nbsp;: view</p>
+
+<h1>Galerie courante</h1>
+<p>Nom&nbsp;: <?php echo $galerie->name; ?></p>
+<p>Description&nbsp;: <?php echo $galerie->description; ?></p>
+<p>Propriétaire&nbsp;: <?php echo $galerie->username; ?></p>
+<p>Nombre de photographies&nbsp;: <?php echo $galerie->nb; ?></p>
index f3adcf0..473bc28 100644 (file)
@@ -1,6 +1,6 @@
-Alias /appblanche /var/git/zf2biz/application-blanche/public
+Alias /galerie /var/git/zf2biz/galerie/public
 
-<Directory /var/git/zf2biz/application-blanche/public>
+<Directory /var/git/zf2biz/galerie/public>
        Order deny,allow
        Allow from all
 
index 9f3a510..9242fcb 100644 (file)
@@ -1,10 +1,10 @@
 <VirtualHost *:80>
-       ServerName appblanche.local
-       DocumentRoot /var/git/zf2biz/application-blanche/public
+       ServerName galerie.local
+       DocumentRoot /var/git/zf2biz/gallerie/public
 
        SetEnv APPLICATION_ENV "development"
 
-       <Directory /var/git/zf2biz/application-blanche/public>
+       <Directory /var/git/zf2biz/galerie/public>
                Order deny,allow
                Allow from all
 
index 4578c85..df89675 100644 (file)
@@ -2,4 +2,6 @@
 .composer
 composer
 zendframework
+doctrine
+symfony
 autoload.php
index e7ae619..c615e66 100644 (file)
@@ -89,11 +89,11 @@ abstract class Manager extends AbstractTableGateway
  
     public function save(Entity $entity)
     {
-        if ($this->is_new()) {
+        if ($this->is_new($entity)) {
             $this->insert(
                 $entity->toUpdatableArray()
             );
-        } elseif ($this->getGalerie(extract_primary($entity))) {
+        } elseif ($this->any($this->extract_primary($entity))) {
             $this->update(
                 $entity->toUpdatableArray(),
                 $entity->toPrimaryArray()