diff --git a/src/Controller/Component/NotifierComponent.php b/src/Controller/Component/NotifierComponent.php index f0c4a8a..9b25dc8 100644 --- a/src/Controller/Component/NotifierComponent.php +++ b/src/Controller/Component/NotifierComponent.php @@ -109,6 +109,32 @@ public function getNotifications($userId = null, $state = null) return $query->toArray(); } + + /** + * getI18nNotifications + * + * Returns a list of translated notifications. + * + * @param int|null $userId Id of the user. + * @param bool|null $state The state of notifications: `true` for unread, `false` for read, `null` for all. + * @return array + */ + public function getI18nNotifications($userId = null, $state = null) + { + if (!$userId) { + $userId = $this->Controller->Auth->user('id'); + } + + $model = TableRegistry::get('Notifier.Notifications'); + + $query = $model->find('translations')->where(['Notifications.user_id' => $userId])->order(['created' => 'desc']); + + if (!is_null($state)) { + $query->where(['Notifications.state' => $state]); + } + + return $query->toArray(); + } /** * countNotifications diff --git a/src/Model/Entity/Notification.php b/src/Model/Entity/Notification.php index c36299e..b5e7a1c 100644 --- a/src/Model/Entity/Notification.php +++ b/src/Model/Entity/Notification.php @@ -1,4 +1,5 @@ _properties['template'], $templates) && array_key_exists($lang, $templates[$this->_properties['template']])) { + $template = $templates[$this->_properties['template']][$lang]; + + if (isset($this->_translations[$lang]['vars'])) { + $vars = json_decode($this->_translations[$lang]['vars'], true); + } else { + $vars = json_decode($this->_properties['vars'], true); + } + + if (isset($template[$property])) { + return Text::insert($template[$property], $vars); + } + } + + return ''; + } + /** * Virtual fields * diff --git a/src/Model/Table/NotificationsTable.php b/src/Model/Table/NotificationsTable.php index b45659d..fa47bd8 100644 --- a/src/Model/Table/NotificationsTable.php +++ b/src/Model/Table/NotificationsTable.php @@ -43,6 +43,10 @@ public function initialize(array $config) $this->displayField('title'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); + $this->addBehavior('Translate', [ + 'fields' => ['vars'], + 'allowEmptyTranslations' => false + ]); } /** diff --git a/src/Utility/NotificationManager.php b/src/Utility/NotificationManager.php index 28a90a8..cf55cbb 100644 --- a/src/Utility/NotificationManager.php +++ b/src/Utility/NotificationManager.php @@ -1,4 +1,5 @@ notify([ + * 'users' => 1, + * 'template' => 'newOrder', + * 'vars' => [ + * 'en' => [ + * 'receiver' => $receiver->name + * 'link' => '/en/order/], + * 'fr' => [ + * 'receiver' => $receiver->name + * 'link' => '/fr/order/], + * ], + * ]); + * ``` + * + * @param array $data Data with options. + * @return string The tracking_id to follow the notification. + */ + public function notifyI18n($data) + { + $model = TableRegistry::get('Notifier.Notifications'); + + $_data = [ + 'users' => [], + 'recipientLists' => [], + 'template' => 'default', + 'vars' => [], + 'tracking_id' => $this->getTrackingId() + ]; + + $data = array_merge($_data, $data); + + foreach ((array)$data['recipientLists'] as $recipientList) { + $list = (array)$this->getRecipientList($recipientList); + $data['users'] = array_merge($data['users'], $list); + } + + foreach ((array)$data['users'] as $user) { + $entity = $model->newEntity(); + + $entity->set('template', $data['template']); + $entity->set('tracking_id', $data['tracking_id']); + + $entity->set('vars', current($data['vars'])); + foreach ($data['vars'] as $lang => $vars) { + $entity->translation($lang)->set(['vars' => $vars], ['guard' => false]); + } + + $entity->set('state', 1); + $entity->set('user_id', $user); + + $model->save($entity); + } + + return $data['tracking_id']; + } + /** * addRecipientList * @@ -182,6 +254,42 @@ public function addTemplate($name, $options = []) Configure::write('Notifier.templates.' . $name, $options); } + /** + * addI18nTemplate + * + * Adds localized template. + * + * ### Example + * + * $this->Notifier->addTemplate('newUser', [ + * 'en' => [ + * 'title' => 'New User: :name', + * 'body' => 'The user :email has been registered'], + * 'fr' => [ + * 'title' => 'Nouvel utilisateur : :name', + * 'body' => 'L\'utilisateur :email vient de s\'inscrire'], + * ]); + * + * This code contains the variables `title` and `body`. + * + * @param string $name Unique name. + * @param array $options Options. + * @return void + */ + public function addI18nTemplate($name, $options = []) + { + $_options = [ + 'en' => [ + 'title' => 'Notification', + 'body' => '', + ] + ]; + + $options = array_merge($_options, $options); + + Configure::write('Notifier.templates.i18n.' . $name, $options); + } + /** * getTemplate * @@ -209,6 +317,34 @@ public function getTemplate($name, $type = null) return false; } + /** + * getI18nTemplate + * + * Returns the requested localized template. + * If the template or type does not exists, `false` will be returned. + * + * @param string $lang Language code. + * @param string $name Name of the template. + * @param string|null $type The type like `title` or `body`. Leave empty to get the whole template. + * @return array|string|bool + */ + public function getI18nTemplate($lang, $name, $type = null) + { + $templates = Configure::read('Notifier.templates.i18n'); + + if (array_key_exists($name, $templates)) { + if ($type == 'title') { + return $templates[$name]['title']; + } + if ($type == 'body') { + return $templates[$name]['body']; + } + return $templates[$name]; + } + + return false; + } + /** * getTrackingId * diff --git a/tests/TestCase/Controller/Component/NotifierComponentTest.php b/tests/TestCase/Controller/Component/NotifierComponentTest.php index d8b9e89..23e5069 100644 --- a/tests/TestCase/Controller/Component/NotifierComponentTest.php +++ b/tests/TestCase/Controller/Component/NotifierComponentTest.php @@ -29,7 +29,8 @@ class NotifierComponentTest extends TestCase { public $fixtures = [ - 'plugin.notifier.notifications' + 'plugin.notifier.notifications', + 'core.translates' ]; public function setUp() @@ -108,6 +109,29 @@ public function testGetNotifications() $this->assertEquals(2, count($this->Notifier->getNotifications(2, false))); } + public function testGetI18nNotifications() + { + $this->Manager->notify(['users' => [1, 1, 1, 2, 2]]); + + $this->assertEquals(3, count($this->Notifier->getI18nNotifications(1))); + $this->assertEquals(3, count($this->Notifier->getI18nNotifications(1, true))); + $this->assertEquals(0, count($this->Notifier->getI18nNotifications(1, false))); + $this->assertEquals(2, count($this->Notifier->getI18nNotifications(2))); + $this->assertEquals(2, count($this->Notifier->getI18nNotifications(2, true))); + $this->assertEquals(0, count($this->Notifier->getI18nNotifications(2, false))); + + $this->Notifier->markAsRead(2, 1); + $this->Notifier->markAsRead(5, 2); + $this->Notifier->markAsRead(6, 2); + + $this->assertEquals(3, count($this->Notifier->getI18nNotifications(1))); + $this->assertEquals(2, count($this->Notifier->getI18nNotifications(1, true))); + $this->assertEquals(1, count($this->Notifier->getI18nNotifications(1, false))); + $this->assertEquals(2, count($this->Notifier->getI18nNotifications(2))); + $this->assertEquals(0, count($this->Notifier->getI18nNotifications(2, true))); + $this->assertEquals(2, count($this->Notifier->getI18nNotifications(2, false))); + } + public function testMarkAsReadWithAuth() { $this->Manager->notify(['users' => [1, 1, 1, 1, 1]]); diff --git a/tests/TestCase/Model/Table/NotificationsTableTest.php b/tests/TestCase/Model/Table/NotificationsTableTest.php index 98f19f1..6a7d422 100644 --- a/tests/TestCase/Model/Table/NotificationsTableTest.php +++ b/tests/TestCase/Model/Table/NotificationsTableTest.php @@ -1,4 +1,5 @@ assertEquals('New Notification', $entity->title); $this->assertEquals('Bob has sent Leonardo a notification about Programming Stuff', $entity->body); } + + public function testI18nEntity() + { + NotificationManager::instance()->addI18nTemplate('newOrder', [ + 'en' => [ + 'title' => 'New order', + 'body' => ':username bought :product' + ], + 'fr' => [ + 'title' => 'Nouvelle commande', + 'body' => ':username a acheté :product' + ] + ]); + + $notify = NotificationManager::instance()->notifyI18n([ + 'users' => 1, + 'template' => 'newOrder', + 'vars' => [ + 'en' => [ + 'username' => 'Bob', + 'product' => 'a car' + ], + 'fr' => [ + 'username' => 'Bob', + 'product' => 'une voiture' + ] + ] + ]); + + I18n::locale('en'); + $entity = $this->Notifications->get(2); + + $this->assertEquals('newOrder', $entity->template); + $this->assertEquals('New order', $entity->getI18n('title', 'en')); + $this->assertEquals('Bob bought a car', $entity->getI18n('body', 'en')); + + I18n::locale('fr'); + $entity = $this->Notifications->get(2); + + $this->assertEquals('newOrder', $entity->template); + $this->assertEquals('Nouvelle commande', $entity->getI18n('title', 'fr')); + $this->assertEquals('Bob a acheté une voiture', $entity->getI18n('body', 'fr')); + } } diff --git a/tests/TestCase/Utility/NotificationManagerTest.php b/tests/TestCase/Utility/NotificationManagerTest.php index 7176be1..8c59876 100644 --- a/tests/TestCase/Utility/NotificationManagerTest.php +++ b/tests/TestCase/Utility/NotificationManagerTest.php @@ -23,7 +23,8 @@ class NotificationManagerTest extends TestCase { public $fixtures = [ - 'plugin.notifier.notifications' + 'plugin.notifier.notifications', + 'core.translates' ]; public function setUp()