Commit 88e68fa1 authored by Marcello Pivanti's avatar Marcello Pivanti
Browse files

Initial Commit

parents
# amos-favorites
Extension for add a content, like news, events, etc..., in the favorites.
## Installation
### 1. Add module to your application
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```bash
composer require elitedivision/amos-favorites
```
or add this row
```
"elitedivision/amos-favorites": "dev-master"
```
to the require section of your `composer.json` file.
### 2. Add module configuration
Add module to your main config in backend like this:
```php
<?php
'modules' => [
'favorites' => [
'class' => 'elitedivision\amos\favorites\AmosFavorites',
'modelsEnabled' => [
/**
* Add here the classnames of the models where you want the comments
* (i.e. 'elitedivision\amos\news\models\News')
*/
]
],
],
```
### 3. Apply migrations
To apply migrations you can launch this command:
```bash
php yii migrate/up --migrationPath=@vendor/elitedivision/amos-favorites/src/migrations
```
or add this row to your migrations config in console:
```php
<?php
return [
'@vendor/elitedivision/amos-favorites/src/migrations',
];
```
{
"name": "arter/amos-favorites",
"description": "Favorites - plugin",
"keywords": [
"amos",
"yii2",
"favorites"
],
"type": "plugin",
"license": "BSD-3-Clause",
"require": {
"php": ">=5.4.0",
"arter/amos-core": "~1.9",
"arter/amos-admin": ">=1.8",
"arter/amos-notify": "~1.3"
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
},
"autoload": {
"psr-4": {
"elitedivision\\amos\\favorites\\": "src"
}
}
}
\ No newline at end of file
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\favorites;
use elitedivision\amos\core\module\AmosModule;
use elitedivision\amos\core\module\ModuleInterface;
/**
* Class AmosFavorites
* @package elitedivision\amos\favorites
*/
class AmosFavorites extends AmosModule implements ModuleInterface
{
public static $CONFIG_FOLDER = 'config';
/**
* @var string|boolean the layout that should be applied for views within this module. This refers to a view name
* relative to [[layoutPath]]. If this is not set, it means the layout value of the [[module|parent module]]
* will be taken. If this is false, layout will be disabled within this module.
*/
public $layout = 'main';
/**
* @inheritdoc
*/
public $controllerNamespace = 'elitedivision\amos\favorites\controllers';
public $newFileMode = 0666;
public $name = 'Favorites';
/**
* @var array $modelsEnabled
*/
public $modelsEnabled = [];
/**
* @return string
*/
public static function getModuleName()
{
return 'favorites';
}
/**
* @inheritdoc
*/
public function init()
{
parent::init();
\Yii::setAlias('@elitedivision/amos/' . static::getModuleName() . '/controllers/', __DIR__ . '/controllers/');
// custom initialization code goes here
\Yii::configure($this, require(__DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php'));
}
/**
* @inheritdoc
*/
public function getWidgetGraphics()
{
return NULL;
}
/**
* @inheritdoc
*/
public function getWidgetIcons()
{
return [];
}
/**
* @inheritdoc
*/
protected function getDefaultModels()
{
return [];
}
}
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\config
* @category CategoryName
* @author Elite Division S.r.l.
*/
return [
];
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\controllers
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\favorites\controllers;
use elitedivision\amos\core\record\Record;
use elitedivision\amos\favorites\AmosFavorites;
use elitedivision\amos\favorites\exceptions\FavoritesException;
use elitedivision\amos\favorites\widgets\FavoriteWidget;
use elitedivision\amos\notificationmanager\AmosNotify;
use Yii;
use yii\web\Controller as YiiController;
use yii\web\NotFoundHttpException;
/**
* Class FavoriteController
* @package elitedivision\amos\favorites\controllers
*/
class FavoriteController extends YiiController
{
/**
* @var string $layout
*/
public $layout = 'main';
/**
* @inheritdoc
*/
public function init() {
parent::init();
$this->setUpLayout();
// custom initialization code goes here
}
/**
* The action manages the favorite add or remove.
* @return string
* @throws FavoritesException
*/
public function actionFavorite()
{
// If the request is not AJAX throws an exception because this action can only be called via AJAX.
if (!Yii::$app->getRequest()->getIsAjax()) {
throw new FavoritesException(AmosFavorites::t('amosfavorites', 'This action cannot be reached directly'));
}
$retVal = [
'success' => 0,
'nowFavorite' => 0,
'nowNotFavorite' => 1,
'msg' => '',
'favoriteBtnTitle' => ''
];
// If the request is not via POST method or there is at least one parameter missing stop the execution.
if (!Yii::$app->getRequest()->post()) {
$retVal['msg'] = AmosFavorites::t('amosfavorites', 'Request not via POST method.');
return json_encode($retVal);
}
$post = Yii::$app->getRequest()->post();
// Missing request parameters.
if (!isset($post['id']) || !isset($post['className'])) {
$retVal['msg'] = AmosFavorites::t('amosfavorites', 'Missing request parameters.');
return json_encode($retVal);
}
/** @var AmosNotify $notify */
$notify = Yii::$app->getModule('notify');
if (is_null($notify)) {
$retVal['msg'] = AmosFavorites::t('amosfavorites', 'Notify module not present.');
return json_encode($retVal);
}
$model = $this->findModel($post['id'], $post['className']);
$readPerm = $this->makeReadPermission($model);
if (Yii::$app->user->can($readPerm, ['model' => $model])) {
$alreadyFavorite = $notify->isFavorite($model, Yii::$app->user->id);
if ($alreadyFavorite) {
$ok = $notify->favouriteOff(Yii::$app->user->id, $post['className'], $post['id']);
return $this->returnValues($ok, $retVal, 'OFF');
} else {
$ok = $notify->favouriteOn(Yii::$app->user->id, $post['className'], $post['id']);
return $this->returnValues($ok, $retVal, 'ON');
}
} else {
$retVal['msg'] = AmosFavorites::t('amosfavorites', 'User cannot read the content.');
return json_encode($retVal);
}
}
/**
* Make the final return values array and then encode it in JSON.
* @param bool $ok
* @param array $retVal
* @param string $type
* @return string
*/
private function returnValues($ok, $retVal, $type)
{
$retVal['success'] = ($ok ? 1 : 0);
if (($ok && ($type == 'ON')) || (!$ok && ($type == 'OFF'))) {
$retVal['nowFavorite'] = 1;
$retVal['nowNotFavorite'] = 0;
$retVal['favoriteBtnTitle'] = FavoriteWidget::favoriteBtnTitle(true);
} elseif ((!$ok && ($type == 'ON')) || ($ok && ($type == 'OFF'))) {
$retVal['nowFavorite'] = 0;
$retVal['nowNotFavorite'] = 1;
$retVal['favoriteBtnTitle'] = FavoriteWidget::favoriteBtnTitle(false);
}
if ($type == 'ON') {
$retVal['msg'] = ($ok ?
AmosFavorites::t('amosfavorites', 'Favorite successfully added.') :
AmosFavorites::t('amosfavorites', 'Error while adding favorite.'));
} elseif ($type == 'OFF') {
$retVal['msg'] = ($ok ?
AmosFavorites::t('amosfavorites', 'Favorite successfully removed.') :
AmosFavorites::t('amosfavorites', 'Error while removing favorite.'));
}
return json_encode($retVal);
}
/**
* Find the content model.
* @param int $id
* @param string $className
* @return Record
* @throws NotFoundHttpException
*/
private function findModel($id, $className)
{
/** @var Record $className */
$model = $className::findOne($id);
if (is_null($model)) {
throw new NotFoundHttpException(AmosFavorites::t('amosfavorites', 'The requested page does not exist.'));
}
return $model;
}
/**
* Return the read permission for a model by his class name.
* @param Record $model
* @return string
*/
private function makeReadPermission($model)
{
$modelClassName = $model::className();
$splitModelClassName = explode("\\", $modelClassName);
$modelName = end($splitModelClassName);
$modelNameUpper = strtoupper($modelName);
return $modelNameUpper . '_READ';
}
/**
* @param null $layout
* @return bool
*/
public function setUpLayout($layout = null){
if ($layout === false){
$this->layout = false;
return true;
}
$module = \Yii::$app->getModule('layout');
if(empty($module)){
$this->layout = '@vendor/elitedivision/amos-core/views/layouts/' . (!empty($layout) ? $layout : $this->layout);
return true;
}
$this->layout = (!empty($layout)) ? $layout : $this->layout;
return true;
}
}
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\exceptions
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\favorites\exceptions;
/**
* Class FavoritesException
* @package elitedivision\amos\favorites\exceptions
*/
class FavoritesException extends \Exception
{
public function __construct($message, $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
public function __toString()
{
return __CLASS__ . ": [{$this->code}]: {$this->message}\n{$this->getFile()}:{$this->getLine()}\n";
}
}
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\i18n\en-GB
* @category CategoryName
* @author Elite Division S.r.l.
*/
return [
'Add to favorites' => 'Add to favorites',
'Error while adding favorite.' => 'Error while adding favorite.',
'Error while removing favorite.' => 'Error while removing favorite.',
'Favorite successfully added.' => 'Favorite successfully added.',
'Favorite successfully removed.' => 'Favorite successfully removed.',
'FavoriteWidget: model required' => 'FavoriteWidget: model required',
'Missing request parameters.' => 'Missing request parameters.',
'Notify module not present.' => 'Notify module not present.',
'Remove favorite' => 'Remove favorite',
'Request not via POST method.' => 'Request not via POST method.',
'The requested page does not exist.' => 'The requested page does not exist.',
'This action cannot be reached directly' => 'This action cannot be reached directly',
'User cannot read the content.' => 'User cannot read the content.',
];
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\i18n\en-US
* @category CategoryName
* @author Elite Division S.r.l.
*/
return [
'Add to favorites' => 'Add to favorites',
'Error while adding favorite.' => 'Error while adding favorite.',
'Error while removing favorite.' => 'Error while removing favorite.',
'Favorite successfully added.' => 'Favorite successfully added.',
'Favorite successfully removed.' => 'Favorite successfully removed.',
'FavoriteWidget: model required' => 'FavoriteWidget: model required',
'Missing request parameters.' => 'Missing request parameters.',
'Notify module not present.' => 'Notify module not present.',
'Remove favorite' => 'Remove favorite',
'Request not via POST method.' => 'Request not via POST method.',
'The requested page does not exist.' => 'The requested page does not exist.',
'This action cannot be reached directly' => 'This action cannot be reached directly',
'User cannot read the content.' => 'User cannot read the content.',
];
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\i18n\it-IT
* @category CategoryName
* @author Elite Division S.r.l.
*/
return [
'Add to favorites' => 'Aggiungi ai preferiti',
'Error while adding favorite.' => 'Errore durante l\'aggiunta del preferito',
'Error while removing favorite.' => 'Errore durante la rimozione del preferito',
'Favorite successfully added.' => 'Preferito aggiunto correttamente.',
'Favorite successfully removed.' => 'Preferito rimosso correttamente.',
'FavoriteWidget: model required' => 'FavoriteWidget: model obbligatorio',
'Missing request parameters.' => 'Parametri mancanti nella richiesta.',
'Notify module not present.' => 'Modulo notify non presente.',
'Remove favorite' => 'Rimuovi preferito',
'Request not via POST method.' => 'La richiesta non è stata eseguita con il metodo POST.',
'The requested page does not exist.' => 'La pagina richiesta non esiste.',
'This action cannot be reached directly' => 'Questa action non può essere chiamata direttamente',
'User cannot read the content.' => 'L\'utente non ha i permessi di lettura per questo contenuto.',
];
<?php
/**
* Art-ER Attrattività, ricerca e territorio dell’Emilia-Romagna
* OPEN 2.0
*
*
* @package elitedivision\amos\favorites\widgets
* @category CategoryName
* @author Elite Division S.r.l.
*/
namespace elitedivision\amos\favorites\widgets;
use elitedivision\amos\core\helpers\Html;
use elitedivision\amos\core\icons\AmosIcons;
use elitedivision\amos\favorites\AmosFavorites;
use elitedivision\amos\favorites\exceptions\FavoritesException;
use elitedivision\amos\notificationmanager\AmosNotify;
use yii\base\Widget;
use yii\web\View;
/**
* Class FavoriteWidget
*
* Widget to show the favorite icon.
*
* @package elitedivision\amos\favorites\widgets
*/
class FavoriteWidget extends Widget
{
public $layout = '{beginContainerSection}{favoriteButton}{endContainerSection}';
/**
* @var \elitedivision\amos\core\record\Record $model
*/
public $model;
/**
* @var array $containerOptions Default to ['id' => 'favorite-container-MODEL_ID']
*/
public $containerOptions = [];
/**
* @var bool $isAlreadyFavorite
*/
private $isAlreadyFavorite = false;
/**
* @throws FavoritesException
*/
public function init()
{
parent::init();
if (is_null($this->model)) {
throw new FavoritesException(AmosFavorites::t('amosfavorites', 'FavoriteWidget: model required'));
}
}
/**
* @return string
*/
public function getLayout()
{
return $this->layout;
}
/**
* @inheritdoc
*/
public function run()
{
if ($this->model->isNewRecord) {
return '';
}
/** @var AmosFavorites $favorites */
$favorites = \Yii::$app->getModule('favorites');
if (!isset($favorites->modelsEnabled) || !in_array($this->model->className(), $favorites->modelsEnabled)) {
return false;
}
$this->initDefaultOptions();
$content = preg_replace_callback("/{\\w+}/", function ($matches) {
$content = $this->renderSection($matches[0]);
return $content === false ? $matches[0] : $content;
}, $this->layout);
$this->registerWidgetJs();
return $content;
}
/**
* Set default options values.
*/
private function initDefaultOptions()
{
$this->containerOptions['id'] = 'favorite-container-' . $this->model->id;
$this->containerOptions['class'] = 'pull-left favorites-container';
}
/**
* Return the container id.
* @return string
*/
public function getContainerId()
{
return $this->containerOptions['id'];
}
/**
* Renders a section of the specified name.
* If the named section is not supported, false will be returned.
* @param string $name the section name, e.g., `{summary}`, `{items}`.
* @return string|boolean the rendering result of the section, or false if the named section is not supported.
*/
public function renderSection($name)
{
switch ($name) {
case '{beginContainerSection}':
return $this->renderBeginContainerSection();
case '{favoriteButton}':
return $this->favoriteButton();
case '{endContainerSection}':
return $this->renderEndContainerSection();