1
0
mirror of https://github.com/devcode-it/openstamanager.git synced 2025-03-09 15:50:14 +01:00

Miglioramento hook ed email

This commit is contained in:
Thomas Zilio 2019-08-26 18:02:05 +02:00
parent 27c97da691
commit ebea9ea807
42 changed files with 844 additions and 703 deletions

View File

@ -2,6 +2,7 @@
include_once __DIR__.'/core.php';
use Models\MailTemplate;
use Models\Note;
use Modules\Checklists\Check;
use Modules\Checklists\Checklist;
@ -203,16 +204,15 @@ elseif (filter('op') == 'sort_checks') {
}
}
// Invio email
// Inizializzazione email
elseif (post('op') == 'send-email') {
$id_template = post('template');
$template = MailTemplate::find(post('template'));
// Inizializzazione
$mail = new Notifications\EmailNotification();
$mail->setTemplate($id_template, $id_record);
$mail = \Models\Mail::build($template, $id_record);
// Rimozione allegati predefiniti
$mail->setAttachments([]);
$mail->resetAttachments();
$mail->resetPrints();
// Destinatari
$receivers = array_clean(post('destinatari'));
@ -222,29 +222,25 @@ elseif (post('op') == 'send-email') {
}
// Contenuti
$mail->setSubject(post('subject'));
$mail->setContent(post('body'));
$mail->subject = post('subject');
$mail->content = post('body');
// Conferma di lettura
$mail->read_notify = post('read_notify');
// Stampe da allegare
$prints = post('prints');
foreach ($prints as $print) {
$mail->addPrint($print, $id_record);
$mail->addPrint($print);
}
// Allegati originali
$files = post('attachments');
foreach ($files as $file) {
$mail->addUpload($file);
$mail->addAttachment($file);
}
// Invio mail
try {
$mail->send(true); // Il valore true impone la gestione degli errori tramite eccezioni
flash()->info(tr('Email inviata correttamente!'));
} catch (PHPMailer\PHPMailer\Exception $e) {
flash()->error(tr("Errore durante l'invio dell'email").': '.$e->errorMessage());
}
$mail->save();
}
// Inclusione di eventuale plugin personalizzato

View File

@ -114,6 +114,16 @@ switch (get('op')) {
break;
case 'prepare-hook':
$hook_id = filter('id');
$hook = Hook::find($hook_id);
$response = $hook->prepare();
echo json_encode($response);
break;
case 'flash':
$response = flash()->getMessages();

View File

@ -1,7 +1,77 @@
/**
*
*/
function startHooks() {
$.ajax({
url: globals.rootdir + "/ajax.php",
type: "get",
data: {
op: "hooks",
},
success: function(data) {
hooks = JSON.parse(data);
function executeHook(hook, length){
$("#hooks").append('<li id="hook-loader-' + hook.id + '"><a href="#">' + globals.translations.hookExecuting.replace('_NAME_', hook.name) + '</a></li>');
$("#hooks-header").text(globals.translations.hooksExecuting);
$("#hooks-number").text(hooks.length);
if (hooks.length == 0) {
$("#hooks-loading").hide();
$("#hooks-number").text(0);
$("#hooks-header").text(globals.translations.hookNone);
}
hooks.forEach(function(item, index){
startHook(item);
});
},
});
}
/**
*
* @param hook
*/
function startHook(hook){
var element_id = "hook-" + hook.id;
$("#hooks").append('<li class="hook-element" id="' + element_id + '"><a href="#">' + globals.translations.hookExecuting.replace('_NAME_', hook.name) + '</a></li>');
element_id = "#" + element_id;
$.ajax({
url: globals.rootdir + "/ajax.php",
type: "get",
data: {
op: "prepare-hook",
id: hook.id,
},
success: function(data) {
var result = JSON.parse(data);
addHookCount("#hooks-counter");
if (result){
renderHook(element_id, result);
if (result.execute){
addHookCount("#hooks-notified");
executeHook(hook, element_id, true)
} else {
$(element_id).remove();
}
} else {
executeHook(hook, element_id)
}
},
});
}
/**
*
* @param hook
* @param element_id
*/
function executeHook(hook, element_id, is_background){
$.ajax({
url: globals.rootdir + "/ajax.php",
type: "get",
@ -10,35 +80,22 @@ function executeHook(hook, length){
id: hook.id,
},
success: function(data) {
result = JSON.parse(data);
var result = JSON.parse(data);
$("#hook-loader-" + hook.id).remove();
notification = '<li class="hook-element"><a href="' + (result.link ? result.link : "#") + '"><i class="' + result.icon + '"></i><span class="small" > ' + result.message + '</span></a></li>';
// Inserimento della notifica
hooks_number = $("#hooks-number");
number = parseInt(hooks_number.text());
number = isNaN(number) ? 0 : number;
renderHook(element_id, result);
if (!is_background) {
if (result.notify) {
number++;
$("#hooks").prepend(notification);
addHookCount("#hooks-notified");
} else {
//$("#hooks").append(notification);
$(element_id).remove();
}
}
hooks_number.text(number);
// Contatore dell'esecuzione degli hook
hooks_counter = $("#hooks-counter");
counter = parseInt(hooks_counter.text());
counter++;
hooks_counter.text(counter);
// Rimozione eventuale della rotella di caricamento
if(counter == hooks.length) {
var counter = $("#hooks-counter").text();
var number = $("#hooks-notified").text();
if(counter == $("#hooks-number").text()) {
$("#hooks-loading").hide();
if (number > 1){
@ -54,3 +111,26 @@ function executeHook(hook, length){
},
});
}
/**
* Aggiunta dell'hook al numero totale.
*/
function addHookCount(id) {
var hooks_number = $(id);
var number = parseInt(hooks_number.text());
number = isNaN(number) ? 0 : number;
number++;
hooks_number.text(number);
return number;
}
/**
*
* @param element_id
* @param result
*/
function renderHook(element_id, result) {
$(element_id).html('<a href="' + (result.link ? result.link : "#") + '"><i class="' + result.icon + '"></i><span class="small" > ' + result.message + '</span></a>');
}

View File

@ -1,8 +1,10 @@
<?php
use Notifications\EmailNotification;
include_once __DIR__.'/core.php';
$mail = Mail::get();
$mail = new EmailNotification();
$bug_email = 'info@openstamanager.com';
$user = Auth::user();

View File

@ -4,6 +4,7 @@ return [
'include' => 'Common',
'modules/aggiornamenti' => 'Modules\Aggiornamenti',
'modules/anagrafiche' => 'Modules\Anagrafiche',
'modules/backups' => 'Modules\Backups',
'modules/articoli' => 'Modules\Articoli',
'modules/checklists' => 'Modules\Checklists',
'modules/ritenute' => 'Modules\Ritenute',

View File

@ -53,40 +53,20 @@ if (Auth::check()) {
echo '
<script>
$(document).ready(function() {
// Toast
alertPush();
// Orologio
clock();
$.ajax({
url: globals.rootdir + "/ajax.php",
type: "get",
data: {
op: "hooks",
},
success: function(data) {
hooks = JSON.parse(data);
$("#hooks-header").text(globals.translations.hooksExecuting);
if (hooks.length == 0) {
$("#hooks-loading").hide();
$("#hooks-number").text(0);
$("#hooks-header").text(globals.translations.hookNone);
}
hooks.forEach(function(item, index){
executeHook(item, hooks.length);
});
},
});
// Hooks
startHooks();
});
</script>';
}
echo '
<script>$(document).ready(init)</script>';
echo '
<script>$(document).ready(init)</script>
</body>
</html>';

View File

@ -1,28 +0,0 @@
<?php
namespace Common;
use Models\Hook;
abstract class HookManager
{
abstract public function manage();
abstract public function response($results);
public static function update($results)
{
$hook = self::getHook();
$hook->updateCache($results);
}
protected static function getHook()
{
$class = get_called_class();
$hook = Hook::where('class', $class)->first();
return $hook;
}
}

View File

@ -314,8 +314,9 @@ if (Auth::check()) {
<i class="fa fa-bell-o"></i>
<span class="label label-warning">
<span id="hooks-loading"><i class="fa fa-spinner fa-spin"></i></span>
<span id="hooks-number"></span>
<span id="hooks-notified"></span>
<span id="hooks-counter" class="hide">0</span>
<span id="hooks-number" class="hide">0</span>
</span>
</a>
<ul class="dropdown-menu">

View File

@ -16,19 +16,6 @@ switch ($op) {
// Rimozione log vecchi
$dbo->query('DELETE FROM `zz_operations` WHERE DATE_ADD(`created_at`, INTERVAL 30*24*60*60 SECOND) <= NOW()');
// Auto backup del database giornaliero
if (setting('Backup automatico')) {
$result = Backup::daily();
if (!isset($result)) {
flash()->info(tr('Backup saltato perché già esistente!'));
} elseif (!empty($result)) {
flash()->info(tr('Backup automatico eseguito correttamente!'));
} else {
flash()->error(tr('Errore durante la generazione del backup automatico!'));
}
}
} else {
$status = auth()->getCurrentStatus();
@ -172,13 +159,7 @@ echo '/> '.tr('Mantieni attiva la sessione').'
<script>
$(document).ready( function(){
$("#login").click(function(){
$("#login").text("';
if ($dbo->isInstalled() && !Update::isUpdateAvailable() && setting('Backup automatico')) {
echo tr('Backup automatico in corso');
} else {
echo tr('Autenticazione');
}
echo '...");
$("#login").text("'.tr('Autenticazione').'...");
});
if( $("input[name=username]").val() == ""){

View File

@ -1,10 +1,12 @@
<?php
use Models\MailTemplate;
include_once __DIR__.'/core.php';
$template = Mail::getTemplate(get('id'));
$module = Modules::get($id_module);
$smtp = Mail::get($template['id_smtp']);
$template = MailTemplate::find(get('id'));
$module = $template->module;
$smtp = $template->account;
$body = $template['body'];
$subject = $template['subject'];
@ -79,7 +81,7 @@ echo '
</div>';
// Stampe
$selected_prints = $dbo->fetchArray('SELECT id_print FROM zz_email_print WHERE id_email = '.prepare($template['id']));
$selected_prints = $dbo->fetchArray('SELECT id_print FROM em_template_print WHERE id_email = '.prepare($template['id']));
$selected = array_column($selected_prints, 'id_print');
echo '

View File

@ -2,16 +2,16 @@
namespace Modules\Aggiornamenti;
use Common\HookManager;
use GuzzleHttp\Client;
use Hooks\CachedManager;
use Modules;
use Update;
class UpdateHook extends HookManager
class UpdateHook extends CachedManager
{
protected static $client = null;
public function manage()
public function execute()
{
$result = self::isAvailable();

View File

@ -3,10 +3,10 @@
namespace Modules\Articoli;
use Common\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules;
use Modules\Interventi\Components\Articolo as ArticoloIntervento;
use Uploads;
use Illuminate\Database\Eloquent\SoftDeletes;
class Articolo extends Model
{

View File

@ -0,0 +1,36 @@
<?php
namespace Modules\Backups;
use Backup;
use Hooks\Manager;
class BackupHook extends Manager
{
public function manage()
{
$result = Backup::daily();
return $result;
}
public function response($update)
{
return [
'icon' => 'fa fa-file-o text-info',
'message' => tr('Backup completato!'),
'notify' => true,
];
}
public function prepare()
{
$result = setting('Backup automatico') && !Backup::isDailyComplete() && self::getHook()->processing == 0;
return [
'icon' => 'fa fa-file-o text-danger',
'message' => tr('Backup in corso...'),
'execute' => $result,
];
}
}

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../core.php';
switch (post('op')) {
case 'add':
$dbo->insert('zz_emails', [
$dbo->insert('em_templates', [
'name' => post('name'),
'id_module' => post('module'),
'id_smtp' => post('smtp'),
@ -18,7 +18,7 @@ switch (post('op')) {
break;
case 'update':
$dbo->update('zz_emails', [
$dbo->update('em_templates', [
'name' => post('name'),
'id_smtp' => post('smtp'),
'icon' => post('icon'),
@ -30,14 +30,14 @@ switch (post('op')) {
'read_notify' => post('read_notify'),
], ['id' => $id_record]);
$dbo->sync('zz_email_print', ['id_email' => $id_record], ['id_print' => (array) post('prints')]);
$dbo->sync('em_template_print', ['id_email' => $id_record], ['id_print' => (array) post('prints')]);
flash()->info(tr('Informazioni salvate correttamente!'));
break;
case 'delete':
$dbo->query('UPDATE zz_emails SET deleted_at = NOW() WHERE id='.prepare($id_record));
$dbo->query('UPDATE em_templates SET deleted_at = NOW() WHERE id='.prepare($id_record));
flash()->info(tr('Template delle email eliminato!'));

View File

@ -62,7 +62,7 @@ include_once __DIR__.'/../../core.php';
<?php
// Stampe
$selected_prints = $dbo->fetchArray('SELECT id_print FROM zz_email_print WHERE id_email = '.prepare($id_record));
$selected_prints = $dbo->fetchArray('SELECT id_print FROM em_template_print WHERE id_email = '.prepare($id_record));
$selected = array_column($selected_prints, 'id_print');
echo '

View File

@ -1,5 +1,5 @@
<?php
if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT * FROM zz_emails WHERE id='.prepare($id_record).' AND deleted_at IS NULL');
$record = $dbo->fetchOne('SELECT * FROM em_templates WHERE id='.prepare($id_record).' AND deleted_at IS NULL');
}

View File

@ -7,7 +7,7 @@ $r = $dbo->fetchOne('SELECT co_documenti.*,
an_anagrafiche.pec,
an_anagrafiche.ragione_sociale,
co_tipidocumento.descrizione AS tipo_documento,
(SELECT pec FROM zz_smtps WHERE zz_smtps.id='.prepare($template['id_smtp']).') AS is_pec
(SELECT pec FROM em_accounts WHERE em_accounts.id='.prepare($template['id_smtp']).') AS is_pec
FROM co_documenti
INNER JOIN an_anagrafiche ON co_documenti.idanagrafica=an_anagrafiche.idanagrafica
INNER JOIN co_tipidocumento ON co_tipidocumento.id=co_documenti.idtipodocumento

View File

@ -5,7 +5,7 @@ $r = $dbo->fetchOne('SELECT co_scadenziario.*, co_documenti.*,
an_anagrafiche.pec,
an_anagrafiche.ragione_sociale,
co_scadenziario.da_pagare - co_scadenziario.pagato AS totale,
(SELECT pec FROM zz_smtps WHERE zz_smtps.id='.prepare($template['id_smtp']).') AS is_pec,
(SELECT pec FROM em_accounts WHERE em_accounts.id='.prepare($template['id_smtp']).') AS is_pec,
(SELECT descrizione FROM co_pagamenti WHERE co_pagamenti.id = co_documenti.idpagamento) AS pagamento
FROM co_scadenziario
INNER JOIN co_documenti ON co_documenti.id = co_scadenziario.iddocumento

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../core.php';
switch (post('op')) {
case 'add':
$dbo->insert('zz_smtps', [
$dbo->insert('em_accounts', [
'name' => post('name'),
'from_name' => post('from_name'),
'from_address' => post('from_address'),
@ -19,10 +19,10 @@ switch (post('op')) {
case 'update':
$predefined = post('predefined');
if (!empty($predefined)) {
$dbo->query('UPDATE zz_smtps SET predefined = 0');
$dbo->query('UPDATE em_accounts SET predefined = 0');
}
$dbo->update('zz_smtps', [
$dbo->update('em_accounts', [
'name' => post('name'),
'note' => post('note'),
'server' => post('server'),
@ -83,7 +83,7 @@ switch (post('op')) {
break;
case 'delete':
$dbo->query('UPDATE zz_smtps SET deleted_at = NOW() WHERE id='.prepare($id_record));
$dbo->query('UPDATE em_accounts SET deleted_at = NOW() WHERE id='.prepare($id_record));
flash()->info(tr('Account email eliminato!'));

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../core.php';
switch ($resource) {
case 'smtp':
$query = 'SELECT id AS id, name AS descrizione FROM zz_smtps |where| ORDER BY name';
$query = 'SELECT id AS id, name AS descrizione FROM em_accounts |where| ORDER BY name';
foreach ($elements as $element) {
$filter[] = 'id = '.prepare($element);

View File

@ -82,7 +82,7 @@ include_once __DIR__.'/../../core.php';
<?php
// Collegamenti diretti
// Template email collegati a questo account
$elementi = $dbo->fetchArray('SELECT `id`, `name` FROM `zz_emails` WHERE `id_smtp` = '.prepare($id_record));
$elementi = $dbo->fetchArray('SELECT `id`, `name` FROM `em_templates` WHERE `id_smtp` = '.prepare($id_record));
if (!empty($elementi)) {
echo '

View File

@ -3,5 +3,5 @@
include_once __DIR__.'/../../core.php';
if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT * FROM zz_smtps WHERE id='.prepare($id_record).' AND deleted_at IS NULL');
$record = $dbo->fetchOne('SELECT * FROM em_accounts WHERE id='.prepare($id_record).' AND deleted_at IS NULL');
}

View File

@ -37,7 +37,7 @@ if ($record['can_delete']) {
</div>
<div class="col-md-4">
{[ "type": "select", "label": "<?php echo tr('Template email'); ?>", "name": "email", "value": "$id_email$", "values": "query=SELECT id, name AS descrizione FROM zz_emails WHERE id_module = <?php echo Modules::get('Interventi')['id']; ?> AND deleted_at IS NULL", "disabled": <?php echo intval(empty($record['notifica'])); ?> ]}
{[ "type": "select", "label": "<?php echo tr('Template email'); ?>", "name": "email", "value": "$id_email$", "values": "query=SELECT id, name AS descrizione FROM em_templates WHERE id_module = <?php echo Modules::get('Interventi')['id']; ?> AND deleted_at IS NULL", "disabled": <?php echo intval(empty($record['notifica'])); ?> ]}
</div>
<div class="col-md-6">

View File

@ -2,12 +2,12 @@
namespace Plugins\ImportFE;
use Common\HookManager;
use Hooks\CachedManager;
use Modules;
class InvoiceHook extends HookManager
class InvoiceHook extends CachedManager
{
public function manage()
public function execute()
{
$list = Interaction::getInvoiceList();

View File

@ -2,12 +2,12 @@
namespace Plugins\ReceiptFE;
use Common\HookManager;
use Hooks\CachedManager;
use Modules;
class ReceiptHook extends HookManager
class ReceiptHook extends CachedManager
{
public function manage()
public function execute()
{
$list = Interaction::getReceiptList();

View File

@ -78,11 +78,11 @@ class Backup
}
/**
* Effettua il backup giornaliero.
* Controlla se il backup giornaliero è stato effettuato.
*
* @return bool|null
*/
public static function daily()
public static function isDailyComplete()
{
// Costruzione del pattern
$replaces = self::getReplaces();
@ -100,8 +100,18 @@ class Backup
// Individuazione dei backup
$backups = self::getList($pattern);
return !empty($backups);
}
/**
* Effettua il backup giornaliero.
*
* @return bool|null
*/
public static function daily()
{
// Creazione del backup eventuale
if (empty($backups)) {
if (!self::isDailyComplete()) {
return self::create();
}
}

View File

@ -2,6 +2,8 @@
namespace HTMLBuilder\Manager;
use Models\MailTemplate;
/**
* @since 2.4
*/
@ -36,7 +38,7 @@ class ButtonManager implements ManagerInterface
'icon' => $print['icon'],
];
} else {
$template = \Mail::getTemplate($options['id']);
$template = MailTemplate::find($options['id']);
$result = [
'link' => ROOTDIR.'/mail.php?id_module='.$options['id_module'].'&id_record='.$options['id_record'].'&id='.$options['id'],
@ -85,7 +87,7 @@ class ButtonManager implements ManagerInterface
if ($options['type'] == 'print') {
$results = \Prints::getModulePrints($options['id_module']);
} else {
$results = \Mail::getModuleTemplates($options['id_module']);
$results = MailTemplate::where('id_module', $options['id_module'])->get()->toArray();
}
return $results;

View File

@ -25,7 +25,7 @@ class EmailManager implements ManagerInterface
$database = database();
// Visualizzo il log delle operazioni di invio email
$operations = $database->fetchArray('SELECT created_at, options, (SELECT name FROM zz_emails WHERE id = id_email) AS email, (SELECT username FROM zz_users WHERE id = id_utente) AS user FROM zz_operations WHERE id_record = '.prepare($options['id_record']).' AND id_module = '.prepare($options['id_module'])." AND op = 'send-email' AND id_email IS NOT NULL ORDER BY created_at DESC");
$operations = $database->fetchArray('SELECT created_at, options, (SELECT name FROM em_templates WHERE id = id_email) AS email, (SELECT username FROM zz_users WHERE id = id_utente) AS user FROM zz_operations WHERE id_record = '.prepare($options['id_record']).' AND id_module = '.prepare($options['id_module'])." AND op = 'send-email' AND id_email IS NOT NULL ORDER BY created_at DESC");
if (empty($operations)) {
return ' ';

View File

@ -0,0 +1,87 @@
<?php
namespace Hooks;
use Carbon\Carbon;
use Carbon\CarbonInterval;
abstract class CachedManager extends Manager
{
protected static $cache = null;
protected static $is_cached = null;
abstract public function execute();
public static function getCache()
{
if (!isset(self::$cache)) {
$hook = self::getHook();
$cache = database()->selectOne('zz_hook_cache', '*', ['hook_id' => $hook->id], ['id' => 'DESC']);
self::$cache = $cache;
}
return self::$cache;
}
public static function update($results)
{
$hook = self::getHook();
// Rimozione cache precedente
$database = database();
$database->delete('zz_hook_cache', [
'hook_id' => $hook->id,
]);
// Aggiunta del risultato come cache
$cache = json_encode($results);
$database->insert('zz_hook_cache', [
'hook_id' => $hook->id,
'results' => $cache,
]);
self::$cache = $results;
self::$is_cached = null;
}
public static function isCached()
{
if (!isset(self::$is_cached)) {
$hook = self::getHook();
$cache = self::getCache();
$is_cached = false;
if (!empty($cache)) {
$date = new Carbon($cache['created_at']);
$interval = CarbonInterval::make($hook->frequency);
$date = $date->add($interval);
$now = new Carbon();
$is_cached = $date->greaterThan($now);
}
self::$is_cached = $is_cached;
}
return self::$is_cached;
}
public function manage()
{
if (self::isCached()) {
$results = self::getCache()['results'];
// Interpretazione della cache
$results = json_decode($results, true);
} else {
$results = $this->execute();
self::update($results);
}
return $results;
}
}

48
src/Hooks/Manager.php Normal file
View File

@ -0,0 +1,48 @@
<?php
namespace Hooks;
use Models\Hook;
abstract class Manager
{
/**
* Restituisce le informazioni sull'esecuzione dell'hook.
*
* @return mixed
*/
abstract public function manage();
/**
* Restituisce le informazioni per la visualizzazione dell'hook.
*
* @param $results
*
* @return array
*/
abstract public function response($results);
/**
* Restituisce le informazioni per l'inizializzazione dell'hook.
*
* @return array|null
*/
public function prepare()
{
return null;
}
/**
* Restituisce l'hook Eloquent relativo alla classe.
*
* @return Hook|null
*/
protected static function getHook()
{
$class = get_called_class();
$hook = Hook::where('class', $class)->first();
return $hook;
}
}

View File

@ -1,284 +0,0 @@
<?php
use Models\MailAccount;
/**
* Classe per gestire le email in base alle impostazioni, basata sul framework open-source PHPMailer.
*
* @since 2.3
*/
class Mail extends PHPMailer\PHPMailer\PHPMailer
{
/** @var array Elenco degli account email disponibili */
protected static $accounts = [];
/** @var array Elenco dei template email disponibili */
protected static $templates = [];
protected static $references = [];
/** @var array Elenco dei template email per modulo */
protected static $modules = [];
protected $infos = [];
public function __construct($account = null, $exceptions = null)
{
parent::__construct($exceptions);
$this->CharSet = 'UTF-8';
// Configurazione di base
$config = self::get($account);
// Preparazione email
$this->IsHTML(true);
if (!empty($config['server'])) {
$this->IsSMTP(true);
// Impostazioni di debug
$this->SMTPDebug = App::debug() ? 2 : 0;
$this->Debugoutput = function ($str, $level) {
$this->infos[] = $str;
};
// Impostazioni dell'host
$this->Host = $config['server'];
$this->Port = $config['port'];
// Impostazioni di autenticazione
if (!empty($config['username'])) {
$this->SMTPAuth = true;
$this->Username = $config['username'];
$this->Password = $config['password'];
}
// Impostazioni di sicurezza
if (in_array(strtolower($config['encryption']), ['ssl', 'tls'])) {
$this->SMTPSecure = strtolower($config['encryption']);
}
if (!empty($config['ssl_no_verify'])) {
$this->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
];
}
}
$this->From = $config['from_address'];
$this->FromName = $config['from_name'];
$this->WordWrap = 78;
}
/**
* Restituisce tutte le informazioni di tutti gli account email presenti.
*
* @return array
*/
public static function getAccounts()
{
return MailAccount::getAll();
}
/**
* Restituisce le informazioni relative a un singolo account email specificato.
*
* @param string|int $account
*
* @return array
*/
public static function get($account = null)
{
$accounts = self::getAccounts();
$result = MailAccount::get($account);
if (empty($result)) {
$result = $accounts->first(function ($item) {
return !empty($item->predefined);
});
}
return $result;
}
/**
* Restituisce tutte le informazioni di tutti i template presenti.
*
* @return array
*/
public static function getTemplates()
{
if (empty(self::$templates)) {
$database = database();
$results = $database->fetchArray('SELECT * FROM zz_emails WHERE deleted_at IS NULL');
$templates = [];
$references = [];
// Inizializzazione dei riferimenti
foreach (Modules::getModules() as $module) {
self::$modules[$module['id']] = [];
}
foreach ($results as $result) {
$templates[$result['id']] = $result;
$references[$result['name']] = $result['id'];
self::$modules[$result['id_module']][] = $result['id'];
}
self::$templates = $templates;
self::$references = $references;
}
return self::$templates;
}
/**
* Restituisce le informazioni relative a un singolo template specificato.
*
* @param string|int $template
*
* @return array
*/
public static function getTemplate($template)
{
$templates = self::getTemplates();
if (!is_numeric($template) && !empty(self::$references[$template])) {
$template = self::$references[$template];
}
return $templates[$template];
}
/**
* Restituisce le informazioni relative ai template di un singolo modulo specificato.
*
* @param string|int $module
*
* @return array
*/
public static function getModuleTemplates($module)
{
$module_id = Modules::get($module)['id'];
self::getTemplates();
$result = [];
foreach ((array) self::$modules[$module_id] as $value) {
$result[] = self::getTemplate($value);
}
return $result;
}
/**
* Testa la connessione al server SMTP.
*
* @return bool
*/
public function testSMTP()
{
if ($this->smtpConnect()) {
$this->smtpClose();
return true;
}
return false;
}
/**
* Invia l'email impostata.
*
* @throws Exception
*
* @return bool
*/
public function send()
{
if (empty($this->AltBody)) {
$this->AltBody = strip_tags($this->Body);
}
$exception = null;
try {
$result = parent::send();
} catch (PHPMailer\PHPMailer\Exception $e) {
$result = false;
$exception = $e;
}
$this->SmtpClose();
// Segnalazione degli errori
if (!$result) {
$logger = logger();
foreach ($this->infos as $info) {
$logger->addRecord(\Monolog\Logger::ERROR, $info);
}
}
if (!empty($exception)) {
throw $exception;
}
return $result;
}
public function setTemplate(array $template)
{
// Reply To
if (!empty($template['reply_to'])) {
$this->AddReplyTo($template['reply_to']);
}
// CC
if (!empty($template['cc'])) {
$this->AddCC($template['cc']);
}
// BCC
if (!empty($template['bcc'])) {
$this->AddBCC($template['bcc']);
}
}
/**
* Aggiunge un destinatario.
*
* @param array $receiver
* @param array $type
*/
public function addReceiver($receiver, $type = null)
{
$pieces = explode('<', $receiver);
$count = count($pieces);
$name = null;
if ($count > 1) {
$email = substr(end($pieces), 0, -1);
$name = substr($receiver, 0, strpos($receiver, '<'.$email));
} else {
$email = $receiver;
}
if (!empty($email)) {
if ($type == 'cc') {
$this->AddCC($email, $name);
} elseif ($type == 'bcc') {
$this->AddBCC($email, $name);
} else {
$this->AddAddress($email, $name);
}
}
}
}

View File

@ -2,8 +2,6 @@
namespace Models;
use Carbon\Carbon;
use Carbon\CarbonInterval;
use Common\Model;
use Illuminate\Database\Eloquent\Builder;
use Traits\StoreTrait;
@ -18,9 +16,6 @@ class Hook extends Model
'permission',
];
protected $cached = null;
protected $use_cached = null;
/**
* Restituisce i permessi relativi all'account in utilizzo.
*
@ -31,75 +26,31 @@ class Hook extends Model
return $this->module->permission;
}
public function getIsCachedAttribute()
{
if (!isset($this->use_cached)) {
$cache = $this->cache;
$use_cached = false;
if (!empty($cache)) {
$date = new Carbon($cache['created_at']);
$interval = CarbonInterval::make($this->frequency);
$date = $date->add($interval);
$now = new Carbon();
$use_cached = $date->greaterThan($now);
}
$this->use_cached = $use_cached;
}
return $this->use_cached;
}
public function execute()
{
$class = $this->class;
$hook = new $class();
if ($this->is_cached) {
$results = $this->cache['results'];
$this->processing = true;
$this->save();
// Interpretazione della cache
$results = json_decode($results, true);
} else {
$results = $hook->manage();
$data = $hook->manage();
$results = $hook->response($data);
$this->updateCache($results);
$this->processing = false;
$this->save();
return $results;
}
return $hook->response($results);
}
public function updateCache($results)
public function prepare()
{
// Rimozione cache precedente
$database = database();
$database->delete('zz_hook_cache', [
'hook_id' => $this->id,
]);
$class = $this->class;
$hook = new $class();
// Aggiunta del risultato come cache
$cache = json_encode($results);
$database->insert('zz_hook_cache', [
'hook_id' => $this->id,
'results' => $cache,
]);
$results = $hook->prepare();
$this->cached = null;
$this->getCacheAttribute();
}
public function getCacheAttribute()
{
if (!isset($this->cached)) {
$cache = database()->selectOne('zz_hook_cache', '*', ['hook_id' => $this->id], ['id' => 'DESC']);
$this->cached = $cache;
}
return $this->cached;
return $results;
}
/* Relazioni Eloquent */

225
src/Models/Mail.php Normal file
View File

@ -0,0 +1,225 @@
<?php
namespace Models;
use Common\Model;
class Mail extends Model
{
protected $table = 'em_emails';
protected $receivers = [];
protected $attachments = [];
protected $prints = [];
protected $options = [];
public static function build($template = null, $id_record = null, $account = null)
{
$model = parent::build();
$model->id_template = $template->id;
$model->id_record = $id_record;
if (!empty($template)) {
$model->resetFromTemplate();
}
if (!empty($account)) {
$model->id_account = $account->id;
}
$model->save();
return $model;
}
/**
* Aggiunge un allegato del gestionale alla notifica.
*
* @param string $file_id
*/
public function addAttachment($file_id)
{
$this->attachments[] = $file_id;
}
public function resetAttachments()
{
$this->attachments = [];
}
/**
* Aggiunge una stampa alla notifica.
*
* @param string|int $print
* @param string $name
*/
public function addPrint($print_id, $name = null)
{
$print = PrintTemplate::find($print_id);
if (empty($name)) {
$name = $print['title'].'.pdf';
}
$this->prints[] = [
'id' => $print['id'],
'name' => $name,
];
}
public function resetPrints()
{
$this->prints = [];
}
/**
* Aggiunge un destinatario alla notifica.
*
* @param string $value
* @param string $type
*/
public function addReceiver($value, $type = null)
{
if (empty($value)) {
return;
}
$list = explode(';', $value);
foreach ($list as $element) {
$this->receivers[] = [
'email' => $element,
'type' => $type,
];
}
}
public function save(array $options = [])
{
$this->setReceiversAttribute($this->receivers);
$this->setAttachmentsAttribute($this->attachments);
$this->setPrintsAttribute($this->prints);
$this->setOptionsAttribute($this->options);
return parent::save($options);
}
// Attributi Eloquent
public function setReceiversAttribute($value)
{
$this->attributes['receivers'] = json_encode($value);
}
public function getReceiversAttribute()
{
return json_decode($this->attributes['receivers'], true);
}
public function setAttachmentsAttribute($value)
{
$this->attributes['attachments'] = json_encode($value);
}
public function getAttachmentsAttribute()
{
return json_decode($this->attributes['attachments'], true);
}
public function setPrintsAttribute($value)
{
$this->attributes['prints'] = json_encode($value);
}
public function getPrintsAttribute()
{
return json_decode($this->attributes['prints'], true);
}
public function setOptionsAttribute($value)
{
$this->attributes['options'] = json_encode($value);
}
public function getOptionsAttribute()
{
return json_decode($this->attributes['options'], true);
}
/**
* Restituisce il titolo della notifica.
*
* @return bool
*/
public function getReadNotifyAttribute()
{
return $this->options['read-notify'];
}
/**
* Imposta il titolo della notifica.
*
* @param bool $value
*/
public function setReadNotifyAttribute($value)
{
$this->options['read-notify'] = boolval($value);
}
/* Relazioni Eloquent */
public function account()
{
return $this->belongsTo(MailAccount::class, 'id_account');
}
public function template()
{
return $this->belongsTo(MailTemplate::class, 'id_template');
}
protected function resetFromTemplate()
{
$template = $this->template;
$this->id_account = $template->account->id;
$this->read_notify = $template->read_notify;
// Contentuto e oggetto
$body = $template->body;
$subject = $template->subject;
if (!empty($this->id_record)) {
$module = $this->template->module;
$body = $module->replacePlaceholders($this->id_record, $body);
$subject = $module->replacePlaceholders($this->id_record, $subject);
}
$this->content = $body;
$this->subject = $subject;
// Reply To
if (!empty($template['reply_to'])) {
$this->options['reply_to'] = $template['reply_to'];
}
// CC
if (!empty($template['cc'])) {
$this->addReceiver($template['cc'], 'cc');
}
// BCC
if (!empty($template['bcc'])) {
$this->addReceiver($template['bcc'], 'bcc');
}
// Incluesione stampe predefinite
$prints = database()->fetchArray('SELECT id_print FROM em_template_print WHERE id_email = '.prepare($template['id']));
foreach ($prints as $print) {
$this->addPrint($print['id_print']);
}
}
}

View File

@ -11,12 +11,12 @@ class MailAccount extends Model
use StoreTrait;
use SoftDeletes;
protected $table = 'zz_smtps';
protected $table = 'em_accounts';
/* Relazioni Eloquent */
public function account()
public function templates()
{
return $this->belongsTo(MailTemplate::class, 'id_smtp');
return $this->hasMany(MailTemplate::class, 'id_smtp');
}
}

View File

@ -11,7 +11,7 @@ class MailTemplate extends Model
use StoreTrait;
use SoftDeletes;
protected $table = 'zz_emails';
protected $table = 'em_templates';
public function getVariablesAttribute()
{
@ -32,6 +32,6 @@ class MailTemplate extends Model
public function account()
{
return $this->hasOne(MailAccount::class, 'id_smtp');
return $this->belongsTo(MailAccount::class, 'id_smtp');
}
}

View File

@ -3,6 +3,7 @@
namespace Models;
use Common\Model;
use Illuminate\Database\Eloquent\Builder;
use Traits\PathTrait;
use Traits\StoreTrait;

View File

@ -2,94 +2,167 @@
namespace Notifications;
use Mail;
use Modules;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
use Models\MailAccount;
use PHPMailer\PHPMailer\PHPMailer;
use Prints;
use Uploads;
class EmailNotification extends Notification
class EmailNotification extends PHPMailer implements NotificationInterface
{
protected $subject = null;
protected $readNotify = false;
protected $mail;
protected $attachments = [];
protected $template = null;
protected $account = null;
protected $attachments = null;
protected $infos = [];
protected $logs = [];
/**
* Restituisce l'account email della notifica.
*
* @return array
*/
public function getAccount()
public function __construct($account = null, $exceptions = null)
{
return Mail::get($this->account);
parent::__construct($exceptions);
$this->CharSet = 'UTF-8';
// Configurazione di base
$config = MailAccount::find($account);
if (empty($config)) {
$config = MailAccount::where('predefined', true)->first();
}
/**
* Imposta l'account email della notifica.
*
* @param string|int $value
*/
public function setAccount($value)
{
$this->account = $value;
// Preparazione email
$this->IsHTML(true);
if (!empty($config['server'])) {
$this->IsSMTP(true);
// Impostazioni di debug
$this->SMTPDebug = \App::debug() ? 2 : 0;
$this->Debugoutput = function ($str, $level) {
$this->infos[] = $str;
};
// Impostazioni dell'host
$this->Host = $config['server'];
$this->Port = $config['port'];
// Impostazioni di autenticazione
if (!empty($config['username'])) {
$this->SMTPAuth = true;
$this->Username = $config['username'];
$this->Password = $config['password'];
}
/**
* Restituisce il template della notifica.
*
* @return array
*/
public function getTemplate()
{
return Mail::getTemplate($this->template);
// Impostazioni di sicurezza
if (in_array(strtolower($config['encryption']), ['ssl', 'tls'])) {
$this->SMTPSecure = strtolower($config['encryption']);
}
/**
* Imposta il template della notifica.
*
* @param string|int $value
* @param int $id_record
*/
public function setTemplate($value, $id_record = null)
{
$this->template = $value;
$template = $this->getTemplate();
$this->setReadNotify($template['read_notify']);
$this->setAccount($template['id_smtp']);
if (!empty($id_record)) {
$module = Modules::get($template['id_module']);
$body = $module->replacePlaceholders($id_record, $template['body']);
$subject = $module->replacePlaceholders($id_record, $template['subject']);
$this->setContent($body);
$this->setSubject($subject);
$this->includeTemplatePrints($id_record);
if (!empty($config['ssl_no_verify'])) {
$this->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
];
}
}
/**
* Include le stampe selezionate dal template.
*
* @param int $id_record
*/
public function includeTemplatePrints($id_record)
{
$template = $this->getTemplate();
$this->From = $config['from_address'];
$this->FromName = $config['from_name'];
$prints = database()->fetchArray('SELECT id_print FROM zz_email_print WHERE id_email = '.prepare($template['id']));
$this->WordWrap = 78;
}
public static function build(\Models\Mail $mail, $exceptions = true)
{
$result = new self($mail->account->id, $exceptions);
$result->setMail($mail);
return $result;
}
public function setMail($mail)
{
$this->mail = $mail;
// Destinatari
$receivers = $mail->receivers;
foreach ($receivers as $receiver) {
$this->addReceiver($receiver['email'], $receiver['type']);
}
// Allegati
$uploads = $mail->attachments;
foreach ($uploads as $upload) {
$this->addUpload($upload);
}
// Stampe
$prints = $mail->prints;
foreach ($prints as $print) {
$this->addPrint($print['id_print'], $id_record);
$this->addPrint($print['id'], $mail->id_record, $print['name']);
}
// Conferma di lettura
if (!empty($mail->read_notify)) {
$this->ConfirmReadingTo = $mail->From;
}
// Reply To
if (!empty($mail->options['reply_to'])) {
$this->AddReplyTo($mail->options['reply_to']);
}
// Oggetto
$this->Subject = $mail->subject;
// Contenuto
$this->Body = $mail->content;
}
public function getMail()
{
return $this->mail;
}
/**
* Invia l'email impostata.
*
* @throws Exception
*
* @return bool
*/
public function send()
{
if (empty($this->AltBody)) {
$this->AltBody = strip_tags($this->Body);
}
$exception = null;
try {
$result = parent::send();
} catch (PHPMailer\PHPMailer\Exception $e) {
$result = false;
$exception = $e;
}
$this->SmtpClose();
// Pulizia file generati
delete(DOCROOT.'/files/notifications/');
// Segnalazione degli errori
if (!$result) {
$logger = logger();
foreach ($this->infos as $info) {
$logger->addRecord(\Monolog\Logger::ERROR, $info);
}
}
if (!empty($exception)) {
throw $exception;
}
return $result;
}
/**
@ -131,20 +204,6 @@ class EmailNotification extends Notification
$this->logs['attachments'][] = $attachment['id'];
}
/**
* Aggiunge un allegato alla notifica.
*
* @param string $path
* @param string $name
*/
public function addAttachment($path, $name = null)
{
$this->attachments[] = [
'path' => $path,
'name' => $name ?: basename($path),
];
}
/**
* Aggiunge una stampa alla notifica.
*
@ -161,7 +220,7 @@ class EmailNotification extends Notification
}
// Utilizzo di una cartella particolare per il salvataggio temporaneo degli allegati
$path = DOCROOT.'/files/notifications/';
$path = DOCROOT.'/files/notifications/'.rand(0, 999);
$info = Prints::render($print['id'], $id_record, $path);
$name = $name ?: $info['name'];
@ -172,117 +231,32 @@ class EmailNotification extends Notification
}
/**
* Restituisce il titolo della notifica.
* Aggiunge un destinatario.
*
* @return string
* @param array $receiver
* @param array $type
*/
public function getSubject()
public function addReceiver($receiver, $type = null)
{
return $this->subject;
$pieces = explode('<', $receiver);
$count = count($pieces);
$name = null;
if ($count > 1) {
$email = substr(end($pieces), 0, -1);
$name = substr($receiver, 0, strpos($receiver, '<'.$email));
} else {
$email = $receiver;
}
/**
* Imposta il titolo della notifica.
*
* @param string $value
*/
public function setSubject($value)
{
$this->subject = $value;
}
/**
* Restituisce il titolo della notifica.
*
* @return bool
*/
public function getReadNotify()
{
return $this->readNotify;
}
/**
* Imposta il titolo della notifica.
*
* @param bool $value
*/
public function setReadNotify($value)
{
$this->readNotify = boolval($value);
}
/**
* Aggiunge un destinatario alla notifica.
*
* @param string $value
* @param string $type
*/
public function addReceiver($value, $type = null)
{
if (empty($value)) {
return;
}
$list = explode(';', $value);
foreach ($list as $element) {
$this->receivers[] = [
'email' => $element,
'type' => $type,
];
}
$this->logs['receivers'][] = $value;
}
public function send($exceptions = false)
{
$account = $this->getAccount();
$mail = new Mail($account['id'], true);
// Template
$template = $this->getTemplate();
if (!empty($template)) {
$mail->setTemplate($template);
}
// Destinatari
$receivers = $this->getReceivers();
foreach ($receivers as $receiver) {
$mail->addReceiver($receiver['email'], $receiver['type']);
}
// Allegati
$attachments = $this->getAttachments();
foreach ($attachments as $attachment) {
$mail->AddAttachment($attachment['path'], $attachment['name']);
}
// Conferma di lettura
if (!empty($this->getReadNotify())) {
$mail->ConfirmReadingTo = $mail->From;
}
// Oggetto
$mail->Subject = $this->getSubject();
// Contenuto
$mail->Body = $this->getContent();
// Invio mail
try {
$mail->send();
operationLog('send-email', [
'id_email' => $template['id'],
], $this->logs);
return true;
} catch (PHPMailerException $e) {
if ($exceptions) {
throw $e;
}
return false;
if (!empty($email)) {
if ($type == 'cc') {
$this->AddCC($email, $name);
} elseif ($type == 'bcc') {
$this->AddBCC($email, $name);
} else {
$this->AddAddress($email, $name);
}
}
}
}

View File

@ -2,7 +2,7 @@
namespace Notifications;
abstract class Notification
abstract class Notification implements NotificationInterface
{
public $receivers = [];
public $content = null;

View File

@ -0,0 +1,8 @@
<?php
namespace Notifications;
interface NotificationInterface
{
public function send();
}

View File

@ -3,6 +3,7 @@
// File e cartelle deprecate
$files = [
'src\API.php',
'src\Mail.php',
'modules\utenti\api',
'modules\stato_servizi\api',
'modules\stati_preventivo\api',

View File

@ -316,3 +316,57 @@ DELETE FROM `zz_plugins` WHERE `name` = 'Pianificazione fatturazione';
-- Aggiunta deleted_at su mg_articoli
ALTER TABLE `mg_articoli` ADD `deleted_at` timestamp NULL DEFAULT NULL;
UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `mg_articoli` WHERE 1=1 AND `deleted_at` IS NULL HAVING 2=2 ORDER BY `descrizione`' WHERE `name` = 'Articoli';
-- Ampliamento hooks
ALTER TABLE `zz_hooks` ADD `processing` BOOLEAN DEFAULT FALSE;
INSERT INTO `zz_hooks` (`id`, `name`, `class`, `frequency`, `id_module`) VALUES (NULL, 'Backup', 'Modules\\Backups\\BackupHook', '1 day', (SELECT `id` FROM `zz_modules` WHERE `name` = 'Backup'));
-- Miglioramento gestione email
ALTER TABLE `zz_emails` RENAME TO `em_templates`;
ALTER TABLE `zz_smtps` RENAME TO `em_accounts`;
ALTER TABLE `zz_email_print` RENAME TO `em_template_print`;
UPDATE zz_modules SET options = REPLACE(options, 'zz_emails', 'em_templates');
UPDATE zz_modules SET options2 = REPLACE(options2, 'zz_emails', 'em_templates');
UPDATE zz_views SET query = REPLACE(query, 'zz_emails', 'em_templates');
CREATE TABLE IF NOT EXISTS `em_campaings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`id_account` int(11) NOT NULL,
`id_template` int(11) NOT NULL,
`state` varchar(25) NOT NULL,
`completed_at` TIMESTAMP NULL DEFAULT NULL,
`deleted_at` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`id_account`) REFERENCES `em_accounts`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_template`) REFERENCES `em_templates`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `em_emails` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_account` int(11) NOT NULL,
`id_template` int(11),
`id_campaign` int(11),
`id_record` int(11),
`subject` varchar(255),
`content` TEXT,
`receivers` TEXT,
`attachments` TEXT,
`prints` TEXT,
`options` TEXT,
`sent_at` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`id_account`) REFERENCES `em_accounts`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_template`) REFERENCES `em_templates`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_campaign`) REFERENCES `em_campaings`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `em_campaing_anagrafica` (
`id_campaign` int(11) NOT NULL,
`id_anagrafica` int(11) NOT NULL,
`id_email` int(11),
FOREIGN KEY (`id_campaign`) REFERENCES `em_campaings`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_anagrafica`) REFERENCES `an_anagrafiche`(`idanagrafica`) ON DELETE CASCADE,
FOREIGN KEY (`id_email`) REFERENCES `em_emails`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;

View File

@ -48,6 +48,12 @@ return [
'dt_spedizione',
'dt_statiddt',
'dt_tipiddt',
'em_template_print',
'em_accounts',
'em_templates',
'em_campaings',
'em_emails',
'em_campaing_anagrafica',
'fe_causali_pagamento_ritenuta',
'fe_modalita_pagamento',
'fe_natura',
@ -87,8 +93,6 @@ return [
'zz_checklist_items',
'zz_documenti',
'zz_documenti_categorie',
'zz_email_print',
'zz_emails',
'zz_field_record',
'zz_fields',
'zz_files',
@ -107,7 +111,6 @@ return [
'zz_segments',
'zz_semaphores',
'zz_settings',
'zz_smtps',
'zz_tokens',
'zz_users',
'zz_user_sedi',