Skip to content

Instantly share code, notes, and snippets.

@akadlec
Created July 16, 2015 06:53
Show Gist options
  • Save akadlec/fc5efd9b85535f48b5e5 to your computer and use it in GitHub Desktop.
Save akadlec/fc5efd9b85535f48b5e5 to your computer and use it in GitHub Desktop.
<?php
/**
* Control.php
*
* @copyright More in license.md
* @license http://www.ipublikuj.eu
* @author Adam Kadlec http://www.ipublikuj.eu
* @package iPublikuj:AccountModule!
* @subpackage DataGrids
* @since 5.0
*
* @date 26.07.14
*/
namespace IPub\AccountModule\DataGrids\Emails;
use Nette;
use Nette\Security as NS;
use Nette\ComponentModel;
use Nette\Utils;
use Tracy\Debugger;
use Kdyby;
use Kdyby\Autowired;
use Kdyby\Doctrine;
use Kdyby\Translation;
use IPub;
use IPub\AccountModule\Entities;
use IPub\AccountModule\Exceptions;
use IPub\AccountModule\Forms;
use IPub\AccountModule\Helpers;
use IPub\AccountModule\Models;
use IPub\AccountModule\Queries;
use IPub\Framework\Application\UI;
use IPub\DataTables;
use IPub\DataTables\Components;
use IPub\DataTables\Components\Columns;
use IPub\ConfirmationDialog\Components as ConfirmationDialog;
class Control extends Components\Control
{
/**
* Implements components rendering
*/
use UI\TControlRender { beforeRender as traitBeforeRender; }
/**
* Implements components entity transformation to handles
*/
use IPub\Application\UI\TEntityCall;
/**
* Implement flash messages
*/
use IPub\FlashMessages\TFlashMessages;
/**
* Implements autowiring extension
*/
use Autowired\AutowireComponentFactories;
/**
* @var Entities\Users\IUser
*/
protected $account;
/**
* @var Models\Emails\IEmailsManager
*/
protected $emailsManager;
/**
* @var Models\Emails\IEmailFacade
*/
protected $emailFacade;
/**
* @var Helpers\VerifyHash
*/
protected $verifyHash;
/**
* @var IPub\Gravatar\Gravatar
*/
protected $gravatar;
/**
* @var string
*/
public $translationDomain = 'account.datagrids.emails';
/**
* @param IPub\Gravatar\Gravatar $gravatar
*/
public function injectGravatar(IPub\Gravatar\Gravatar $gravatar)
{
$this->gravatar = $gravatar;
}
/**
* @param Models\Emails\IEmailsManager $emailsManager
* @param Models\Emails\IEmailFacade $emailFacade
* @param Helpers\VerifyHash $verifyHash
*/
public function __construct(
Models\Emails\IEmailsManager $emailsManager,
Models\Emails\IEmailFacade $emailFacade,
Helpers\VerifyHash $verifyHash
) {
parent::__construct();
// Modules managers
$this->emailsManager = $emailsManager;
// Modules facades
$this->emailFacade = $emailFacade;
// Modules helpers
$this->verifyHash = $verifyHash;
}
/**
* @param \Nette\ComponentModel\IComponent
*/
public function attached($presenter)
{
parent::attached($presenter);
// Set translator domain
$this->setTranslator($this->getTranslator()->domain($this->translationDomain));
}
/**
* Set user account or identity
*
* @param Entities\Users\IUser|NS\IIdentity $account
*
* @return $this
*
* @throws Exceptions\LogicException
*/
public function setAccount($account)
{
if ($account instanceof Entities\Identities\Identity) {
$this->account = $account->getOwner();
} else if ($account instanceof Entities\Users\IUser ) {
$this->account = $account;
} else {
throw new Exceptions\LogicException('This call support only instance of "Nette\Security\IIdentity" or "Entities\Users\IUser", instance of "'. get_class($account) .'" was given');
}
return $this;
}
/**
* @param ComponentModel\IComponent $presenter
*/
protected function configure($presenter)
{
// Store object into variable
$self = $this;
// Remap columns names
$filterMapping = [
];
// Define table primary key
$this->setPrimaryKey('id');
// Data are loaded on demand
$this->enableServerSide();
// Enable processing animation
$this->enableProcessing();
// Enable data grid state saving
$this->enableStateSave();
// And store it into session
$this->saveStateIntoSession();
// Define default sorting
$this->setDefaultSort(['address' => Columns\IColumn::ORDER_DESC]);
// Get data query builder
$qb = $this->emailFacade->getQBForDataGrid();
$qb
->where('e.owner = :owner')
->setParameter(':owner', $this->account);
// Assign data source to the grid
$this->setModel(new IPub\DataTables\DataSources\Doctrine($qb, $filterMapping));
$columnAvatar = $this->addColumnImage('avatar', $this->translationDomain .'.column.avatar.title')
->setClassName('pk-table-width-minimum')
->setImage(function(Entities\Emails\IEmail $row){
return [
'src' => $this->gravatar->buildUrl($row->getAddress(), 40),
'alt' => $row->getAddress(),
'class' => 'uk-img-preserve uk-border-circle'
];
});
$columnAddress = $this->addColumnText('address', $this->translationDomain .'.column.address.title')
->setClassName('uk-text-nowrap');
$columnAddress
->addFilterText($this->translationDomain .'.column.address.filter')
->setColumn('address');
$columnVerified = $this->addColumnAction('verified', $this->translationDomain .'.column.verified.title')
->setClassName('uk-text-center')
->enableSearchable()
->enableSortable();
$columnVerified
->addButton('verified')
->showAsLink()
->setClass(function(Entities\Emails\IEmail $row){
// Get user status
return $row->isVerified() ? 'uk-icon-circle uk-text-primary' : 'uk-icon-circle uk-text-muted';
})
->setTitle(function(Entities\Emails\IEmail $row){
// Get user status
return $row->isVerified() ? $this->translationDomain .'.column.verified.tooltip.verified' : $this->translationDomain .'.column.verified.tooltip.notVerified';
})
->addAttributes(function(Entities\Emails\IEmail $row){
return $row->isVerified() ? ['disabled' => 'disabled', 'data-uk-tooltip' => ''] : ['data-uk-tooltip' => ''];
})
->setCallback(function(Entities\Emails\IEmail $row){
// Get user status
$row->isVerified() ? NULL : $this->handleRequestVerification([$row]);
});
$columnVerified
->addFilterSelect($this->translationDomain .'.column.verified.filter', [
'' => $this->translationDomain .'.column.verified.values.none',
TRUE => $this->translationDomain .'.column.verified.values.verified',
FALSE => $this->translationDomain .'.column.verified.values.notVerified',
]);
$columnDefault = $this->addColumnAction('default', $this->translationDomain .'.column.default.title')
->setClassName('uk-text-center')
->enableSearchable()
->enableSortable();
$columnDefault
->addButton('default')
->showAsLink()
->setClass(function(Entities\Emails\IEmail $row){
// Get user status
return $row->isDefault() ? 'uk-icon-circle uk-text-primary' : 'uk-icon-circle uk-text-muted';
})
->setTitle(function(Entities\Emails\IEmail $row){
// Get user status
return $row->isDefault() ? $this->translationDomain .'.column.default.tooltip.default' : ($row->isVerified() ? $this->translationDomain .'.column.default.tooltip.notDefault' : $this->translationDomain .'.column.default.tooltip.notVerified');
})
->addAttributes(function(Entities\Emails\IEmail $row){
return $row->isDefault() || !$row->isVerified() ? ['disabled' => 'disabled', 'data-uk-tooltip' => ''] : ['data-uk-tooltip' => ''];
})
->setCallback(function(Entities\Emails\IEmail $row){
// Get user status
$row->isDefault() || !$row->isVerified() ? NULL : $this->handleSetPrimary([$row]);
});
// Global actions
$this->addGlobalButton('delete', 'deleteEmail.title')
->showAsLink()
->setCallback(function(array $rows){
$params = [];
foreach($rows as $row) {
$params['emails'][] = $row->getId();
}
$this['confirmAction']->showConfirm('delete', $params);
});
$this->addGlobalButton('verify', 'verifyEmail.title')
->showAsLink()
->setCallback(function(array $rows){
$this->handleRequestVerification($rows);
});
}
/**
* Before render component
*
* @throws Exceptions\LogicException
*/
protected function beforeRender()
{
self::traitBeforeRender();
// Check if account entity is set
if (!$this->account) {
throw new Exceptions\LogicException('Missing call ' . get_called_class() . '::setAccount($entity)');
}
}
/**
* Component for action confirmation
*
* @param ConfirmationDialog\IControl $factory
*
* @return ConfirmationDialog\Control
*/
protected function createComponentConfirmAction(ConfirmationDialog\IControl $factory)
{
// Init action confirm
$form = $factory->create();
// Define confirm windows
$form
// Set template defined in presenter
->setTemplateFile($this->getPresenter()->getConfirmerTemplate())
// Email delete confirm
->addConfirmer(
'delete',
[$this, 'handleDelete'],
[$this, 'questionDelete'],
$this->getTranslator()->translate("delete.heading.deleteAddress")
);
return $form;
}
/**
* Create question for delete email dialog
*
* @param ConfirmationDialog\Confirmer $dialog
* @param $params
*
* @return bool|string
*/
public function questionDelete(ConfirmationDialog\Confirmer $dialog, $params)
{
// Set dialog icon
$dialog->setIcon('trash');
// Create question
return $this->getTranslator()->translate("delete.text.deleteAddress", ['count' => count($params['emails'])]);
}
/**
* Handler for delete user emails
*
* @param array $emails
*
* @throws Exceptions\BadRequestException
* @throws Exceptions\ForbiddenRequestException
*/
public function handleDelete(array $emails)
{
// Do the full table redraw
$this->enableFullRedraw();
// Deleted emails count
$deleted = 0;
foreach($emails as $id) {
// Try to load email by id
if ($email = $this->emailFacade->findOneByIdentifier($id)) {
// Check if user is item owner
if ($email->getOwner()->getId() != $this->account->getId()) {
// Store info message
$this->flashNotifier->error("framework.messages.accessOnlyToOwnerRecords");
throw new Exceptions\ForbiddenRequestException;
}
// Only not default email could be deleted
if (!$email->isDefault()) {
try {
// Delete email from database
$this->emailsManager->delete($email);
$deleted++;
} catch (\Exception $ex) {
// Log error message
Debugger::log($ex->getMessage(), Debugger::ERROR);
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain . ".delete.validation.email.notDeleted", ['address' => $email->getAddress()]));
}
// For default email raise error message
} else {
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain . ".delete.validation.email.isDefault", ['address' => $email->getAddress()]));
}
}
}
// Only if some emails were deleted
if ($deleted) {
// Store info message
$this->flashNotifier->success(new Translation\Phrase($this->translationDomain . ".delete.success", $deleted));
} else {
// Store info message
$this->flashNotifier->success(new Translation\Phrase($this->translationDomain . ".delete.validation.email.noEmails"));
}
}
/**
* Handler for marking selected email as default
*
* @param array $emails
*
* @throws Exceptions\ForbiddenRequestException
*/
public function handleSetPrimary(array $emails)
{
// Do the full table redraw
$this->enableFullRedraw();
// Process all emails
foreach($emails as $email) {
// Check if user is item owner
if ($email->getOwner()->getId() != $this->account->getId()) {
// Store info message
$this->flashNotifier->error("framework.messages.accessOnlyToOwnerRecords");
throw new Exceptions\ForbiddenRequestException;
}
// Check if email is verified
if ($email->getVerified()) {
try {
// Deactivate all user emails
foreach ($this->account->getEmails() as $userEmail) {
// Create values for updating
$values = new Utils\ArrayHash();
// Add entity identifier
$values->id = $userEmail->getId();
// Change default status
$values->default = FALSE;
// Updated data in database
$this->emailsManager->update($userEmail, $values);
}
// Create values for updating
$values = new Utils\ArrayHash();
// Add entity identifier
$values->id = $email->getId();
// Change default status
$values->default = TRUE;
// Updated data in database
$this->emailsManager->update($email, $values);
// Store info message
$this->flashNotifier->success($this->translationDomain .".setPrimary.success");
// Only one email could be set as primary
return;
} catch (\Exception $ex) {
// Log error message
Debugger::log($ex->getMessage(), Debugger::ERROR);
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain .".setPrimary.validation.email.notSet", ['address' => $email->getAddress()]));
}
// Email is not verified
} else {
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain .".setPrimary.validation.email.notVerified", ['address' => $email->getAddress()]));
}
}
}
/**
* Handler for sending verification email to selected email
*
* @param array $emails
*
* @throws Exceptions\ForbiddenRequestException
* @throws Exceptions\BadRequestException
*/
public function handleRequestVerification(array $emails)
{
// Do the full table redraw
$this->enableFullRedraw();
// Process all emails
foreach($emails as $email) {
// Check if user is item owner
if ($email->getOwner()->getId() != $this->account->getId()) {
// Store info message
$this->flashNotifier->error("framework.messages.accessOnlyToOwnerRecords");
throw new Exceptions\ForbiddenRequestException;
}
// Email is not verified yer
if (!$email->isVerified()) {
try {
// Create values for updating
$values = new Utils\ArrayHash();
// Add entity identifier
$values->id = $email->getId();
// Add verification info
$values->verificationCreated = new Utils\DateTime();
$values->verificationHash = $this->verifyHash->createKey();
// Save item into database
$this->emailsManager->update($email, $values);
// Store info message
$this->flashNotifier->success(new Translation\Phrase($this->translationDomain . ".verify.success", ["address" => $email->getAddress()]));
} catch (\Exception $ex) {
// Log error message
Debugger::log($ex->getMessage(), Debugger::ERROR);
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain . ".verify.validation.email.notSent", ["address" => $email->getAddress()]));
}
// Email is already verified
} else {
// Store info message
$this->flashNotifier->warning(new Translation\Phrase($this->translationDomain . ".verify.validation.email.isVerified", ["address" => $email->getAddress()]));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment