merge
This commit is contained in:
commit
046a724272
4209 changed files with 1186656 additions and 0 deletions
958
www/analytics/plugins/ScheduledReports/API.php
Normal file
958
www/analytics/plugins/ScheduledReports/API.php
Normal file
|
|
@ -0,0 +1,958 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ScheduledReports;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Date;
|
||||
use Piwik\Db;
|
||||
use Piwik\NoAccessException;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\LanguagesManager\LanguagesManager;
|
||||
use Piwik\Plugins\SegmentEditor\API as APISegmentEditor;
|
||||
use Piwik\Plugins\SitesManager\API as SitesManagerApi;
|
||||
use Piwik\ReportRenderer;
|
||||
use Piwik\ReportRenderer\Html;
|
||||
use Piwik\Site;
|
||||
use Piwik\Translate;
|
||||
use Zend_Mime;
|
||||
|
||||
/**
|
||||
* The ScheduledReports API lets you manage Scheduled Email reports, as well as generate, download or email any existing report.
|
||||
*
|
||||
* "generateReport" will generate the requested report (for a specific date range, website and in the requested language).
|
||||
* "sendEmailReport" will send the report by email to the recipients specified for this report.
|
||||
*
|
||||
* You can also get the list of all existing reports via "getReports", create new reports via "addReport",
|
||||
* or manage existing reports with "updateReport" and "deleteReport".
|
||||
* See also the documentation about <a href='http://piwik.org/docs/email-reports/' target='_blank'>Scheduled Email reports</a> in Piwik.
|
||||
*
|
||||
* @method static \Piwik\Plugins\ScheduledReports\API getInstance()
|
||||
*/
|
||||
class API extends \Piwik\Plugin\API
|
||||
{
|
||||
const VALIDATE_PARAMETERS_EVENT = 'ScheduledReports.validateReportParameters';
|
||||
const GET_REPORT_PARAMETERS_EVENT = 'ScheduledReports.getReportParameters';
|
||||
const GET_REPORT_METADATA_EVENT = 'ScheduledReports.getReportMetadata';
|
||||
const GET_REPORT_TYPES_EVENT = 'ScheduledReports.getReportTypes';
|
||||
const GET_REPORT_FORMATS_EVENT = 'ScheduledReports.getReportFormats';
|
||||
const GET_RENDERER_INSTANCE_EVENT = 'ScheduledReports.getRendererInstance';
|
||||
const PROCESS_REPORTS_EVENT = 'ScheduledReports.processReports';
|
||||
const GET_REPORT_RECIPIENTS_EVENT = 'ScheduledReports.getReportRecipients';
|
||||
const ALLOW_MULTIPLE_REPORTS_EVENT = 'ScheduledReports.allowMultipleReports';
|
||||
const SEND_REPORT_EVENT = 'ScheduledReports.sendReport';
|
||||
|
||||
const OUTPUT_DOWNLOAD = 1;
|
||||
const OUTPUT_SAVE_ON_DISK = 2;
|
||||
const OUTPUT_INLINE = 3;
|
||||
const OUTPUT_RETURN = 4;
|
||||
|
||||
const REPORT_TRUNCATE = 23;
|
||||
|
||||
/**
|
||||
* Creates a new report and schedules it.
|
||||
*
|
||||
* @param int $idSite
|
||||
* @param string $description Report description
|
||||
* @param string $period Schedule frequency: day, week or month
|
||||
* @param int $hour Hour (0-23) when the report should be sent
|
||||
* @param string $reportType 'email' or any other format provided via the ScheduledReports.getReportTypes hook
|
||||
* @param string $reportFormat 'pdf', 'html' or any other format provided via the ScheduledReports.getReportFormats hook
|
||||
* @param array $reports array of reports
|
||||
* @param array $parameters array of parameters
|
||||
* @param bool|int $idSegment Segment Identifier
|
||||
*
|
||||
* @return int idReport generated
|
||||
*/
|
||||
public function addReport($idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
|
||||
$currentUser = Piwik::getCurrentUserLogin();
|
||||
self::ensureLanguageSetForUser($currentUser);
|
||||
|
||||
self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat);
|
||||
|
||||
// report parameters validations
|
||||
$parameters = self::validateReportParameters($reportType, $parameters);
|
||||
|
||||
// validation of requested reports
|
||||
$reports = self::validateRequestedReports($idSite, $reportType, $reports);
|
||||
|
||||
$db = Db::get();
|
||||
$idReport = $db->fetchOne("SELECT max(idreport) + 1 FROM " . Common::prefixTable('report'));
|
||||
|
||||
if ($idReport == false) {
|
||||
$idReport = 1;
|
||||
}
|
||||
|
||||
$db->insert(Common::prefixTable('report'),
|
||||
array(
|
||||
'idreport' => $idReport,
|
||||
'idsite' => $idSite,
|
||||
'login' => $currentUser,
|
||||
'description' => $description,
|
||||
'idsegment' => $idSegment,
|
||||
'period' => $period,
|
||||
'hour' => $hour,
|
||||
'type' => $reportType,
|
||||
'format' => $reportFormat,
|
||||
'parameters' => $parameters,
|
||||
'reports' => $reports,
|
||||
'ts_created' => Date::now()->getDatetime(),
|
||||
'deleted' => 0,
|
||||
));
|
||||
|
||||
return $idReport;
|
||||
}
|
||||
|
||||
private static function ensureLanguageSetForUser($currentUser)
|
||||
{
|
||||
$lang = \Piwik\Plugins\LanguagesManager\API::getInstance()->getLanguageForUser($currentUser);
|
||||
if (empty($lang)) {
|
||||
\Piwik\Plugins\LanguagesManager\API::getInstance()->setLanguageForUser($currentUser, LanguagesManager::getLanguageCodeForCurrentUser());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing report.
|
||||
*
|
||||
* @see addReport()
|
||||
*/
|
||||
public function updateReport($idReport, $idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
|
||||
$scheduledReports = $this->getReports($idSite, $periodSearch = false, $idReport);
|
||||
$report = reset($scheduledReports);
|
||||
$idReport = $report['idreport'];
|
||||
|
||||
$currentUser = Piwik::getCurrentUserLogin();
|
||||
self::ensureLanguageSetForUser($currentUser);
|
||||
|
||||
self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat);
|
||||
|
||||
// report parameters validations
|
||||
$parameters = self::validateReportParameters($reportType, $parameters);
|
||||
|
||||
// validation of requested reports
|
||||
$reports = self::validateRequestedReports($idSite, $reportType, $reports);
|
||||
|
||||
Db::get()->update(Common::prefixTable('report'),
|
||||
array(
|
||||
'description' => $description,
|
||||
'idsegment' => $idSegment,
|
||||
'period' => $period,
|
||||
'hour' => $hour,
|
||||
'type' => $reportType,
|
||||
'format' => $reportFormat,
|
||||
'parameters' => $parameters,
|
||||
'reports' => $reports,
|
||||
),
|
||||
"idreport = '$idReport'"
|
||||
);
|
||||
|
||||
self::$cache = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specific report
|
||||
*
|
||||
* @param int $idReport
|
||||
*/
|
||||
public function deleteReport($idReport)
|
||||
{
|
||||
$APIScheduledReports = $this->getReports($idSite = false, $periodSearch = false, $idReport);
|
||||
$report = reset($APIScheduledReports);
|
||||
Piwik::checkUserHasSuperUserAccessOrIsTheUser($report['login']);
|
||||
|
||||
Db::get()->update(Common::prefixTable('report'),
|
||||
array(
|
||||
'deleted' => 1,
|
||||
),
|
||||
"idreport = '$idReport'"
|
||||
);
|
||||
self::$cache = array();
|
||||
}
|
||||
|
||||
// static cache storing reports
|
||||
public static $cache = array();
|
||||
|
||||
/**
|
||||
* Returns the list of reports matching the passed parameters
|
||||
*
|
||||
* @param bool|int $idSite If specified, will filter reports that belong to a specific idsite
|
||||
* @param bool|string $period If specified, will filter reports that are scheduled for this period (day,week,month)
|
||||
* @param bool|int $idReport If specified, will filter the report that has the given idReport
|
||||
* @param bool $ifSuperUserReturnOnlySuperUserReports
|
||||
* @param bool|int $idSegment If specified, will filter the report that has the given idSegment
|
||||
* @throws Exception
|
||||
* @return array
|
||||
*/
|
||||
public function getReports($idSite = false, $period = false, $idReport = false, $ifSuperUserReturnOnlySuperUserReports = false, $idSegment = false)
|
||||
{
|
||||
Piwik::checkUserHasSomeViewAccess();
|
||||
$cacheKey = (int)$idSite . '.' . (string)$period . '.' . (int)$idReport . '.' . (int)$ifSuperUserReturnOnlySuperUserReports;
|
||||
if (isset(self::$cache[$cacheKey])) {
|
||||
return self::$cache[$cacheKey];
|
||||
}
|
||||
|
||||
$sqlWhere = '';
|
||||
$bind = array();
|
||||
|
||||
// Super user gets all reports back, other users only their own
|
||||
if (!Piwik::hasUserSuperUserAccess()
|
||||
|| $ifSuperUserReturnOnlySuperUserReports
|
||||
) {
|
||||
$sqlWhere .= "AND login = ?";
|
||||
$bind[] = Piwik::getCurrentUserLogin();
|
||||
}
|
||||
|
||||
if (!empty($period)) {
|
||||
$this->validateReportPeriod($period);
|
||||
$sqlWhere .= " AND period = ? ";
|
||||
$bind[] = $period;
|
||||
}
|
||||
if (!empty($idSite)) {
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$sqlWhere .= " AND " . Common::prefixTable('site') . ".idsite = ?";
|
||||
$bind[] = $idSite;
|
||||
}
|
||||
if (!empty($idReport)) {
|
||||
$sqlWhere .= " AND idreport = ?";
|
||||
$bind[] = $idReport;
|
||||
}
|
||||
if (!empty($idSegment)) {
|
||||
$sqlWhere .= " AND idsegment = ?";
|
||||
$bind[] = $idSegment;
|
||||
}
|
||||
|
||||
// Joining with the site table to work around pre-1.3 where reports could still be linked to a deleted site
|
||||
$reports = Db::fetchAll("SELECT report.*
|
||||
FROM " . Common::prefixTable('report') . " AS `report`
|
||||
JOIN " . Common::prefixTable('site') . "
|
||||
USING (idsite)
|
||||
WHERE deleted = 0
|
||||
$sqlWhere", $bind);
|
||||
// When a specific report was requested and not found, throw an error
|
||||
if ($idReport !== false
|
||||
&& empty($reports)
|
||||
) {
|
||||
throw new Exception("Requested report couldn't be found.");
|
||||
}
|
||||
|
||||
foreach ($reports as &$report) {
|
||||
// decode report parameters
|
||||
$report['parameters'] = Common::json_decode($report['parameters'], true);
|
||||
|
||||
// decode report list
|
||||
$report['reports'] = Common::json_decode($report['reports'], true);
|
||||
}
|
||||
|
||||
// static cache
|
||||
self::$cache[$cacheKey] = $reports;
|
||||
|
||||
return $reports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report file.
|
||||
*
|
||||
* @param int $idReport ID of the report to generate.
|
||||
* @param string $date YYYY-MM-DD
|
||||
* @param bool|false|string $language If not passed, will use default language.
|
||||
* @param bool|false|int $outputType 1 = download report, 2 = save report to disk, 3 = output report in browser, 4 = return report content to caller, defaults to download
|
||||
* @param bool|false|string $period Defaults to 'day'. If not specified, will default to the report's period set when creating the report
|
||||
* @param bool|false|string $reportFormat 'pdf', 'html' or any other format provided via the ScheduledReports.getReportFormats hook
|
||||
* @param bool|false|array $parameters array of parameters
|
||||
* @return array|void
|
||||
*/
|
||||
public function generateReport($idReport, $date, $language = false, $outputType = false, $period = false, $reportFormat = false, $parameters = false)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
// load specified language
|
||||
if (empty($language)) {
|
||||
$language = Translate::getLanguageDefault();
|
||||
}
|
||||
|
||||
Translate::reloadLanguage($language);
|
||||
|
||||
$reports = $this->getReports($idSite = false, $_period = false, $idReport);
|
||||
$report = reset($reports);
|
||||
|
||||
$idSite = $report['idsite'];
|
||||
$login = $report['login'];
|
||||
$reportType = $report['type'];
|
||||
|
||||
$this->checkUserHasViewPermission($login, $idSite);
|
||||
|
||||
// override report period
|
||||
if (empty($period)) {
|
||||
$period = $report['period'];
|
||||
}
|
||||
|
||||
// override report format
|
||||
if (!empty($reportFormat)) {
|
||||
self::validateReportFormat($reportType, $reportFormat);
|
||||
$report['format'] = $reportFormat;
|
||||
} else {
|
||||
$reportFormat = $report['format'];
|
||||
}
|
||||
|
||||
// override and/or validate report parameters
|
||||
$report['parameters'] = Common::json_decode(
|
||||
self::validateReportParameters($reportType, empty($parameters) ? $report['parameters'] : $parameters),
|
||||
true
|
||||
);
|
||||
|
||||
// available reports
|
||||
$availableReportMetadata = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite);
|
||||
|
||||
// we need to lookup which reports metadata are registered in this report
|
||||
$reportMetadata = array();
|
||||
foreach ($availableReportMetadata as $metadata) {
|
||||
if (in_array($metadata['uniqueId'], $report['reports'])) {
|
||||
$reportMetadata[] = $metadata;
|
||||
}
|
||||
}
|
||||
|
||||
// the report will be rendered with the first 23 rows and will aggregate other rows in a summary row
|
||||
// 23 rows table fits in one portrait page
|
||||
$initialFilterTruncate = Common::getRequestVar('filter_truncate', false);
|
||||
$_GET['filter_truncate'] = self::REPORT_TRUNCATE;
|
||||
|
||||
$prettyDate = null;
|
||||
$processedReports = array();
|
||||
$segment = self::getSegment($report['idsegment']);
|
||||
foreach ($reportMetadata as $action) {
|
||||
$apiModule = $action['module'];
|
||||
$apiAction = $action['action'];
|
||||
$apiParameters = array();
|
||||
if (isset($action['parameters'])) {
|
||||
$apiParameters = $action['parameters'];
|
||||
}
|
||||
|
||||
$mustRestoreGET = false;
|
||||
|
||||
// all Websites dashboard should not be truncated in the report
|
||||
if ($apiModule == 'MultiSites') {
|
||||
$mustRestoreGET = $_GET;
|
||||
$_GET['enhanced'] = true;
|
||||
|
||||
if ($apiAction == 'getAll') {
|
||||
$_GET['filter_truncate'] = false;
|
||||
|
||||
// when a view/admin user created a report, workaround the fact that "Super User"
|
||||
// is enforced in Scheduled tasks, and ensure Multisites.getAll only return the websites that this user can access
|
||||
$userLogin = $report['login'];
|
||||
if (!empty($userLogin)
|
||||
&& !Piwik::hasTheUserSuperUserAccess($userLogin)
|
||||
) {
|
||||
$_GET['_restrictSitesToLogin'] = $userLogin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$processedReport = \Piwik\Plugins\API\API::getInstance()->getProcessedReport(
|
||||
$idSite, $period, $date, $apiModule, $apiAction,
|
||||
$segment != null ? urlencode($segment['definition']) : false,
|
||||
$apiParameters, $idGoal = false, $language
|
||||
);
|
||||
|
||||
$processedReport['segment'] = $segment;
|
||||
|
||||
// TODO add static method getPrettyDate($period, $date) in Period
|
||||
$prettyDate = $processedReport['prettyDate'];
|
||||
|
||||
if ($mustRestoreGET) {
|
||||
$_GET = $mustRestoreGET;
|
||||
}
|
||||
|
||||
$processedReports[] = $processedReport;
|
||||
}
|
||||
|
||||
// restore filter truncate parameter value
|
||||
if ($initialFilterTruncate !== false) {
|
||||
$_GET['filter_truncate'] = $initialFilterTruncate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when generating the content of scheduled reports.
|
||||
*
|
||||
* This event can be used to modify the report data or report metadata of one or more reports
|
||||
* in a scheduled report, before the scheduled report is rendered and delivered.
|
||||
*
|
||||
* TODO: list data available in $report or make it a new class that can be documented (same for
|
||||
* all other events that use a $report)
|
||||
*
|
||||
* @param array &$processedReports The list of processed reports in the scheduled
|
||||
* report. Entries includes report data and metadata for each report.
|
||||
* @param string $reportType A string ID describing how the scheduled report will be sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
* @param string $outputType The output format of the report, eg, `'html'`, `'pdf'`, etc.
|
||||
* @param array $report An array describing the scheduled report that is being
|
||||
* generated.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::PROCESS_REPORTS_EVENT,
|
||||
array(&$processedReports, $reportType, $outputType, $report)
|
||||
);
|
||||
|
||||
$reportRenderer = null;
|
||||
|
||||
/**
|
||||
* Triggered when obtaining a renderer instance based on the scheduled report output format.
|
||||
*
|
||||
* Plugins that provide new scheduled report output formats should use this event to
|
||||
* handle their new report formats.
|
||||
*
|
||||
* @param ReportRenderer &$reportRenderer This variable should be set to an instance that
|
||||
* extends {@link Piwik\ReportRenderer} by one of the event
|
||||
* subscribers.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
* @param string $outputType The output format of the report, eg, `'html'`, `'pdf'`, etc.
|
||||
* @param array $report An array describing the scheduled report that is being
|
||||
* generated.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::GET_RENDERER_INSTANCE_EVENT,
|
||||
array(&$reportRenderer, $reportType, $outputType, $report)
|
||||
);
|
||||
|
||||
if(is_null($reportRenderer)) {
|
||||
throw new Exception("A report renderer was not supplied in the event " . self::GET_RENDERER_INSTANCE_EVENT);
|
||||
}
|
||||
|
||||
// init report renderer
|
||||
$reportRenderer->setLocale($language);
|
||||
|
||||
// render report
|
||||
$description = str_replace(array("\r", "\n"), ' ', $report['description']);
|
||||
|
||||
list($reportSubject, $reportTitle) = self::getReportSubjectAndReportTitle(Site::getNameFor($idSite), $report['reports']);
|
||||
$filename = "$reportTitle - $prettyDate - $description";
|
||||
|
||||
$reportRenderer->renderFrontPage($reportTitle, $prettyDate, $description, $reportMetadata, $segment);
|
||||
array_walk($processedReports, array($reportRenderer, 'renderReport'));
|
||||
|
||||
switch ($outputType) {
|
||||
|
||||
case self::OUTPUT_SAVE_ON_DISK:
|
||||
|
||||
$outputFilename = strtoupper($reportFormat) . ' ' . ucfirst($reportType) . ' Report - ' . $idReport . '.' . $date . '.' . $idSite . '.' . $language;
|
||||
$outputFilename = $reportRenderer->sendToDisk($outputFilename);
|
||||
|
||||
$additionalFiles = $this->getAttachments($reportRenderer, $report, $processedReports, $prettyDate);
|
||||
|
||||
return array(
|
||||
$outputFilename,
|
||||
$prettyDate,
|
||||
$reportSubject,
|
||||
$reportTitle,
|
||||
$additionalFiles,
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case self::OUTPUT_INLINE:
|
||||
|
||||
$reportRenderer->sendToBrowserInline($filename);
|
||||
break;
|
||||
|
||||
case self::OUTPUT_RETURN:
|
||||
|
||||
return $reportRenderer->getRenderedReport();
|
||||
break;
|
||||
|
||||
default:
|
||||
case self::OUTPUT_DOWNLOAD:
|
||||
$reportRenderer->sendToBrowserDownload($filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function sendReport($idReport, $period = false, $date = false)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$reports = $this->getReports($idSite = false, false, $idReport);
|
||||
$report = reset($reports);
|
||||
|
||||
if ($report['period'] == 'never') {
|
||||
$report['period'] = 'day';
|
||||
}
|
||||
|
||||
if (!empty($period)) {
|
||||
$report['period'] = $period;
|
||||
}
|
||||
|
||||
if (empty($date)) {
|
||||
$date = Date::now()->subPeriod(1, $report['period'])->toString();
|
||||
}
|
||||
|
||||
$language = \Piwik\Plugins\LanguagesManager\API::getInstance()->getLanguageForUser($report['login']);
|
||||
|
||||
// generate report
|
||||
list($outputFilename, $prettyDate, $reportSubject, $reportTitle, $additionalFiles) =
|
||||
$this->generateReport(
|
||||
$idReport,
|
||||
$date,
|
||||
$language,
|
||||
self::OUTPUT_SAVE_ON_DISK,
|
||||
$report['period']
|
||||
);
|
||||
|
||||
if (!file_exists($outputFilename)) {
|
||||
throw new Exception("The report file wasn't found in $outputFilename");
|
||||
}
|
||||
|
||||
$filename = basename($outputFilename);
|
||||
$handle = fopen($outputFilename, "r");
|
||||
$contents = fread($handle, filesize($outputFilename));
|
||||
fclose($handle);
|
||||
|
||||
/**
|
||||
* Triggered when sending scheduled reports.
|
||||
*
|
||||
* Plugins that provide new scheduled report transport mediums should use this event to
|
||||
* send the scheduled report.
|
||||
*
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
* @param array $report An array describing the scheduled report that is being
|
||||
* generated.
|
||||
* @param string $contents The contents of the scheduled report that was generated
|
||||
* and now should be sent.
|
||||
* @param string $filename The path to the file where the scheduled report has
|
||||
* been saved.
|
||||
* @param string $prettyDate A prettified date string for the data within the
|
||||
* scheduled report.
|
||||
* @param string $reportSubject A string describing what's in the scheduled
|
||||
* report.
|
||||
* @param string $reportTitle The scheduled report's given title (given by a Piwik user).
|
||||
* @param array $additionalFiles The list of additional files that should be
|
||||
* sent with this report.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::SEND_REPORT_EVENT,
|
||||
array(
|
||||
$report['type'],
|
||||
$report,
|
||||
$contents,
|
||||
$filename,
|
||||
$prettyDate,
|
||||
$reportSubject,
|
||||
$reportTitle,
|
||||
$additionalFiles
|
||||
)
|
||||
);
|
||||
|
||||
// Update flag in DB
|
||||
Db::get()->update(Common::prefixTable('report'),
|
||||
array('ts_last_sent' => Date::now()->getDatetime()),
|
||||
"idreport = " . $report['idreport']
|
||||
);
|
||||
|
||||
// If running from piwik.php with debug, do not delete the PDF after sending the email
|
||||
if (!isset($GLOBALS['PIWIK_TRACKER_DEBUG']) || !$GLOBALS['PIWIK_TRACKER_DEBUG']) {
|
||||
@chmod($outputFilename, 0600);
|
||||
}
|
||||
}
|
||||
|
||||
private static function getReportSubjectAndReportTitle($websiteName, $reports)
|
||||
{
|
||||
// if the only report is "All websites", we don't display the site name
|
||||
$reportTitle = Piwik::translate('General_Website') . " " . $websiteName;
|
||||
$reportSubject = $websiteName;
|
||||
if (count($reports) == 1
|
||||
&& $reports[0] == 'MultiSites_getAll'
|
||||
) {
|
||||
$reportSubject = Piwik::translate('General_MultiSitesSummary');
|
||||
$reportTitle = $reportSubject;
|
||||
}
|
||||
|
||||
return array($reportSubject, $reportTitle);
|
||||
}
|
||||
|
||||
private static function validateReportParameters($reportType, $parameters)
|
||||
{
|
||||
// get list of valid parameters
|
||||
$availableParameters = array();
|
||||
|
||||
/**
|
||||
* Triggered when gathering the available parameters for a scheduled report type.
|
||||
*
|
||||
* Plugins that provide their own scheduled report transport mediums should use this
|
||||
* event to list the available report parameters for their transport medium.
|
||||
*
|
||||
* @param array $availableParameters The list of available parameters for this report type.
|
||||
* This is an array that maps paramater IDs with a boolean
|
||||
* that indicates whether the parameter is mandatory or not.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
*/
|
||||
Piwik::postEvent(self::GET_REPORT_PARAMETERS_EVENT, array(&$availableParameters, $reportType));
|
||||
|
||||
// unset invalid parameters
|
||||
$availableParameterKeys = array_keys($availableParameters);
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (!in_array($key, $availableParameterKeys)) {
|
||||
unset($parameters[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// test that all required parameters are provided
|
||||
foreach ($availableParameters as $parameter => $mandatory) {
|
||||
if ($mandatory && !isset($parameters[$parameter])) {
|
||||
throw new Exception('Missing parameter : ' . $parameter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when validating the parameters for a scheduled report.
|
||||
*
|
||||
* Plugins that provide their own scheduled reports backend should use this
|
||||
* event to validate the custom parameters defined with {@link ScheduledReports::getReportParameters()}.
|
||||
*
|
||||
* @param array $parameters The list of parameters for the scheduled report.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
*/
|
||||
Piwik::postEvent(self::VALIDATE_PARAMETERS_EVENT, array(&$parameters, $reportType));
|
||||
|
||||
return Common::json_encode($parameters);
|
||||
}
|
||||
|
||||
private static function validateAndTruncateDescription(&$description)
|
||||
{
|
||||
$description = substr($description, 0, 250);
|
||||
}
|
||||
|
||||
private static function validateRequestedReports($idSite, $reportType, $requestedReports)
|
||||
{
|
||||
if (!self::allowMultipleReports($reportType)) {
|
||||
//sms can only contain one report, we silently discard all but the first
|
||||
$requestedReports = array_slice($requestedReports, 0, 1);
|
||||
}
|
||||
|
||||
// retrieve available reports
|
||||
$availableReportMetadata = self::getReportMetadata($idSite, $reportType);
|
||||
|
||||
$availableReportIds = array();
|
||||
foreach ($availableReportMetadata as $reportMetadata) {
|
||||
$availableReportIds[] = $reportMetadata['uniqueId'];
|
||||
}
|
||||
|
||||
foreach ($requestedReports as $report) {
|
||||
if (!in_array($report, $availableReportIds)) {
|
||||
throw new Exception("Report $report is unknown or not available for report type '$reportType'.");
|
||||
}
|
||||
}
|
||||
|
||||
return Common::json_encode($requestedReports);
|
||||
}
|
||||
|
||||
private static function validateCommonReportAttributes($period, $hour, &$description, &$idSegment, $reportType, $reportFormat)
|
||||
{
|
||||
self::validateReportPeriod($period);
|
||||
self::validateReportHour($hour);
|
||||
self::validateAndTruncateDescription($description);
|
||||
self::validateIdSegment($idSegment);
|
||||
self::validateReportType($reportType);
|
||||
self::validateReportFormat($reportType, $reportFormat);
|
||||
}
|
||||
|
||||
private static function validateReportPeriod($period)
|
||||
{
|
||||
$availablePeriods = array('day', 'week', 'month', 'never');
|
||||
if (!in_array($period, $availablePeriods)) {
|
||||
throw new Exception('Period schedule must be one of the following: ' . implode(', ', $availablePeriods));
|
||||
}
|
||||
}
|
||||
|
||||
private static function validateReportHour($hour)
|
||||
{
|
||||
if (!is_numeric($hour) || $hour < 0 || $hour > 23) {
|
||||
throw new Exception('Invalid hour schedule. Should be anything from 0 to 23 inclusive.');
|
||||
}
|
||||
}
|
||||
|
||||
private static function validateIdSegment(&$idSegment)
|
||||
{
|
||||
if (empty($idSegment) || (is_numeric($idSegment) && $idSegment == 0)) {
|
||||
|
||||
$idSegment = null;
|
||||
} elseif (!is_numeric($idSegment)) {
|
||||
|
||||
throw new Exception('Invalid segment identifier. Should be an integer.');
|
||||
} elseif (self::getSegment($idSegment) == null) {
|
||||
|
||||
throw new Exception('Segment with id ' . $idSegment . ' does not exist or SegmentEditor is not activated.');
|
||||
}
|
||||
}
|
||||
|
||||
private static function validateReportType($reportType)
|
||||
{
|
||||
$reportTypes = array_keys(self::getReportTypes());
|
||||
|
||||
if (!in_array($reportType, $reportTypes)) {
|
||||
throw new Exception(
|
||||
'Report type \'' . $reportType . '\' not valid. Try one of the following ' . implode(', ', $reportTypes)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static function validateReportFormat($reportType, $reportFormat)
|
||||
{
|
||||
$reportFormats = array_keys(self::getReportFormats($reportType));
|
||||
|
||||
if (!in_array($reportFormat, $reportFormats)) {
|
||||
throw new Exception(
|
||||
Piwik::translate(
|
||||
'General_ExceptionInvalidReportRendererFormat',
|
||||
array($reportFormat, implode(', ', $reportFormats))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function getReportMetadata($idSite, $reportType)
|
||||
{
|
||||
$availableReportMetadata = array();
|
||||
|
||||
/**
|
||||
* TODO: change this event so it returns a list of API methods instead of report metadata arrays.
|
||||
* Triggered when gathering the list of Piwik reports that can be used with a certain
|
||||
* transport medium.
|
||||
*
|
||||
* Plugins that provide their own transport mediums should use this
|
||||
* event to list the Piwik reports that their backend supports.
|
||||
*
|
||||
* @param array &$availableReportMetadata An array containg report metadata for each supported
|
||||
* report.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
* @param int $idSite The ID of the site we're getting available reports for.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::GET_REPORT_METADATA_EVENT,
|
||||
array(&$availableReportMetadata, $reportType, $idSite)
|
||||
);
|
||||
|
||||
return $availableReportMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function allowMultipleReports($reportType)
|
||||
{
|
||||
$allowMultipleReports = null;
|
||||
|
||||
/**
|
||||
* Triggered when we're determining if a scheduled report transport medium can
|
||||
* handle sending multiple Piwik reports in one scheduled report or not.
|
||||
*
|
||||
* Plugins that provide their own transport mediums should use this
|
||||
* event to specify whether their backend can send more than one Piwik report
|
||||
* at a time.
|
||||
*
|
||||
* @param bool &$allowMultipleReports Whether the backend type can handle multiple
|
||||
* Piwik reports or not.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::ALLOW_MULTIPLE_REPORTS_EVENT,
|
||||
array(&$allowMultipleReports, $reportType)
|
||||
);
|
||||
return $allowMultipleReports;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function getReportTypes()
|
||||
{
|
||||
$reportTypes = array();
|
||||
|
||||
/**
|
||||
* Triggered when gathering all available transport mediums.
|
||||
*
|
||||
* Plugins that provide their own transport mediums should use this
|
||||
* event to make their medium available.
|
||||
*
|
||||
* @param array &$reportTypes An array mapping transport medium IDs with the paths to those
|
||||
* mediums' icons. Add your new backend's ID to this array.
|
||||
*/
|
||||
Piwik::postEvent(self::GET_REPORT_TYPES_EVENT, array(&$reportTypes));
|
||||
|
||||
return $reportTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function getReportFormats($reportType)
|
||||
{
|
||||
$reportFormats = array();
|
||||
|
||||
/**
|
||||
* Triggered when gathering all available scheduled report formats.
|
||||
*
|
||||
* Plugins that provide their own scheduled report format should use
|
||||
* this event to make their format available.
|
||||
*
|
||||
* @param array &$reportFormats An array mapping string IDs for each available
|
||||
* scheduled report format with icon paths for those
|
||||
* formats. Add your new format's ID to this array.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
*/
|
||||
Piwik::postEvent(
|
||||
self::GET_REPORT_FORMATS_EVENT,
|
||||
array(&$reportFormats, $reportType)
|
||||
);
|
||||
|
||||
return $reportFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function getReportRecipients($report)
|
||||
{
|
||||
$recipients = array();
|
||||
|
||||
/**
|
||||
* Triggered when getting the list of recipients of a scheduled report.
|
||||
*
|
||||
* Plugins that provide their own scheduled report transport medium should use this event
|
||||
* to extract the list of recipients their backend's specific scheduled report
|
||||
* format.
|
||||
*
|
||||
* @param array &$recipients An array of strings describing each of the scheduled
|
||||
* reports recipients. Can be, for example, a list of email
|
||||
* addresses or phone numbers or whatever else your plugin
|
||||
* uses.
|
||||
* @param string $reportType A string ID describing how the report is sent, eg,
|
||||
* `'sms'` or `'email'`.
|
||||
* @param array $report An array describing the scheduled report that is being
|
||||
* generated.
|
||||
*/
|
||||
Piwik::postEvent(self::GET_REPORT_RECIPIENTS_EVENT, array(&$recipients, $report['type'], $report));
|
||||
|
||||
return $recipients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
static public function getSegment($idSegment)
|
||||
{
|
||||
if (self::isSegmentEditorActivated() && !empty($idSegment)) {
|
||||
|
||||
$segment = APISegmentEditor::getInstance()->get($idSegment);
|
||||
|
||||
if ($segment) {
|
||||
return $segment;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
public static function isSegmentEditorActivated()
|
||||
{
|
||||
return \Piwik\Plugin\Manager::getInstance()->isPluginActivated('SegmentEditor');
|
||||
}
|
||||
|
||||
private function getAttachments($reportRenderer, $report, $processedReports, $prettyDate)
|
||||
{
|
||||
$additionalFiles = array();
|
||||
|
||||
if ($reportRenderer instanceof Html) {
|
||||
|
||||
foreach ($processedReports as $processedReport) {
|
||||
|
||||
if ($processedReport['displayGraph']) {
|
||||
|
||||
$additionalFiles[] = $this->createAttachment($report, $processedReport, $prettyDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $additionalFiles;
|
||||
}
|
||||
|
||||
private function createAttachment($report, $processedReport, $prettyDate)
|
||||
{
|
||||
$additionalFile = array();
|
||||
|
||||
$segment = self::getSegment($report['idsegment']);
|
||||
|
||||
$segmentName = $segment != null ? sprintf(' (%s)', $segment['name']) : '';
|
||||
|
||||
$processedReportMetadata = $processedReport['metadata'];
|
||||
|
||||
$additionalFile['filename'] =
|
||||
sprintf(
|
||||
'%s - %s - %s %d - %s %d%s.png',
|
||||
$processedReportMetadata['name'],
|
||||
$prettyDate,
|
||||
Piwik::translate('General_Website'),
|
||||
$report['idsite'],
|
||||
Piwik::translate('General_Report'),
|
||||
$report['idreport'],
|
||||
$segmentName
|
||||
);
|
||||
|
||||
$additionalFile['cid'] = $processedReportMetadata['uniqueId'];
|
||||
|
||||
$additionalFile['content'] =
|
||||
ReportRenderer::getStaticGraph(
|
||||
$processedReportMetadata,
|
||||
Html::IMAGE_GRAPH_WIDTH,
|
||||
Html::IMAGE_GRAPH_HEIGHT,
|
||||
$processedReport['evolutionGraph'],
|
||||
$segment
|
||||
);
|
||||
|
||||
$additionalFile['mimeType'] = 'image/png';
|
||||
|
||||
$additionalFile['encoding'] = Zend_Mime::ENCODING_BASE64;
|
||||
|
||||
return $additionalFile;
|
||||
}
|
||||
|
||||
private function checkUserHasViewPermission($login, $idSite)
|
||||
{
|
||||
if (empty($idSite)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$idSitesUserHasAccess = SitesManagerApi::getInstance()->getSitesIdWithAtLeastViewAccess($login);
|
||||
|
||||
if (empty($idSitesUserHasAccess)
|
||||
|| !in_array($idSite, $idSitesUserHasAccess)
|
||||
) {
|
||||
throw new NoAccessException(Piwik::translate('General_ExceptionPrivilege', array("'view'")));
|
||||
}
|
||||
}
|
||||
}
|
||||
92
www/analytics/plugins/ScheduledReports/Controller.php
Normal file
92
www/analytics/plugins/ScheduledReports/Controller.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ScheduledReports;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\LanguagesManager\LanguagesManager;
|
||||
use Piwik\Plugins\SegmentEditor\API as APISegmentEditor;
|
||||
use Piwik\Plugins\SitesManager\API as APISitesManager;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Controller extends \Piwik\Plugin\Controller
|
||||
{
|
||||
const DEFAULT_REPORT_TYPE = ScheduledReports::EMAIL_TYPE;
|
||||
|
||||
public function index()
|
||||
{
|
||||
$view = new View('@ScheduledReports/index');
|
||||
$this->setGeneralVariablesView($view);
|
||||
|
||||
$view->countWebsites = count(APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess());
|
||||
|
||||
// get report types
|
||||
$reportTypes = API::getReportTypes();
|
||||
$view->reportTypes = $reportTypes;
|
||||
$view->defaultReportType = self::DEFAULT_REPORT_TYPE;
|
||||
$view->defaultReportFormat = ScheduledReports::DEFAULT_REPORT_FORMAT;
|
||||
$view->displayFormats = ScheduledReports::getDisplayFormats();
|
||||
|
||||
$reportsByCategoryByType = array();
|
||||
$reportFormatsByReportType = array();
|
||||
$allowMultipleReportsByReportType = array();
|
||||
foreach ($reportTypes as $reportType => $reportTypeIcon) {
|
||||
// get report formats
|
||||
$reportFormatsByReportType[$reportType] = API::getReportFormats($reportType);
|
||||
$allowMultipleReportsByReportType[$reportType] = API::allowMultipleReports($reportType);
|
||||
|
||||
// get report metadata
|
||||
$reportsByCategory = array();
|
||||
$availableReportMetadata = API::getReportMetadata($this->idSite, $reportType);
|
||||
foreach ($availableReportMetadata as $reportMetadata) {
|
||||
$reportsByCategory[$reportMetadata['category']][] = $reportMetadata;
|
||||
}
|
||||
$reportsByCategoryByType[$reportType] = $reportsByCategory;
|
||||
}
|
||||
$view->reportsByCategoryByReportType = $reportsByCategoryByType;
|
||||
$view->reportFormatsByReportType = $reportFormatsByReportType;
|
||||
$view->allowMultipleReportsByReportType = $allowMultipleReportsByReportType;
|
||||
|
||||
$reports = array();
|
||||
$reportsById = array();
|
||||
if (!Piwik::isUserIsAnonymous()) {
|
||||
$reports = API::getInstance()->getReports($this->idSite, $period = false, $idReport = false, $ifSuperUserReturnOnlySuperUserReports = true);
|
||||
foreach ($reports as &$report) {
|
||||
$report['recipients'] = API::getReportRecipients($report);
|
||||
$reportsById[$report['idreport']] = $report;
|
||||
}
|
||||
}
|
||||
$view->reports = $reports;
|
||||
$view->reportsJSON = Common::json_encode($reportsById);
|
||||
|
||||
$view->downloadOutputType = API::OUTPUT_INLINE;
|
||||
|
||||
$view->periods = ScheduledReports::getPeriodToFrequency();
|
||||
$view->defaultPeriod = ScheduledReports::DEFAULT_PERIOD;
|
||||
$view->defaultHour = ScheduledReports::DEFAULT_HOUR;
|
||||
|
||||
$view->language = LanguagesManager::getLanguageCodeForCurrentUser();
|
||||
|
||||
$view->segmentEditorActivated = false;
|
||||
if (API::isSegmentEditorActivated()) {
|
||||
|
||||
$savedSegmentsById = array();
|
||||
foreach (APISegmentEditor::getInstance()->getAll($this->idSite) as $savedSegment) {
|
||||
$savedSegmentsById[$savedSegment['idsegment']] = $savedSegment['name'];
|
||||
}
|
||||
$view->savedSegmentsById = $savedSegmentsById;
|
||||
$view->segmentEditorActivated = true;
|
||||
}
|
||||
|
||||
return $view->render();
|
||||
}
|
||||
}
|
||||
642
www/analytics/plugins/ScheduledReports/ScheduledReports.php
Normal file
642
www/analytics/plugins/ScheduledReports/ScheduledReports.php
Normal file
|
|
@ -0,0 +1,642 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ScheduledReports;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Mail;
|
||||
use Piwik\Menu\MenuTop;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\CoreAdminHome\CustomLogo;
|
||||
use Piwik\Plugins\MobileMessaging\API as APIMobileMessaging;
|
||||
use Piwik\Plugins\MobileMessaging\MobileMessaging;
|
||||
use Piwik\Plugins\SegmentEditor\API as APISegmentEditor;
|
||||
use Piwik\Plugins\UsersManager\API as APIUsersManager;
|
||||
use Piwik\ReportRenderer;
|
||||
use Piwik\ScheduledTask;
|
||||
use Piwik\ScheduledTime;
|
||||
use Piwik\Site;
|
||||
use Piwik\View;
|
||||
use Zend_Mime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ScheduledReports extends \Piwik\Plugin
|
||||
{
|
||||
const MOBILE_MESSAGING_TOP_MENU_TRANSLATION_KEY = 'MobileMessaging_TopMenu';
|
||||
const PDF_REPORTS_TOP_MENU_TRANSLATION_KEY = 'ScheduledReports_EmailReports';
|
||||
|
||||
const DISPLAY_FORMAT_GRAPHS_ONLY_FOR_KEY_METRICS = 1; // Display Tables Only (Graphs only for key metrics)
|
||||
const DISPLAY_FORMAT_GRAPHS_ONLY = 2; // Display Graphs Only for all reports
|
||||
const DISPLAY_FORMAT_TABLES_AND_GRAPHS = 3; // Display Tables and Graphs for all reports
|
||||
const DISPLAY_FORMAT_TABLES_ONLY = 4; // Display only tables for all reports
|
||||
const DEFAULT_DISPLAY_FORMAT = self::DISPLAY_FORMAT_GRAPHS_ONLY_FOR_KEY_METRICS;
|
||||
|
||||
const DEFAULT_REPORT_FORMAT = ReportRenderer::HTML_FORMAT;
|
||||
const DEFAULT_PERIOD = 'week';
|
||||
const DEFAULT_HOUR = '0';
|
||||
|
||||
const EMAIL_ME_PARAMETER = 'emailMe';
|
||||
const EVOLUTION_GRAPH_PARAMETER = 'evolutionGraph';
|
||||
const ADDITIONAL_EMAILS_PARAMETER = 'additionalEmails';
|
||||
const DISPLAY_FORMAT_PARAMETER = 'displayFormat';
|
||||
const EMAIL_ME_PARAMETER_DEFAULT_VALUE = true;
|
||||
const EVOLUTION_GRAPH_PARAMETER_DEFAULT_VALUE = false;
|
||||
|
||||
const EMAIL_TYPE = 'email';
|
||||
|
||||
static private $availableParameters = array(
|
||||
self::EMAIL_ME_PARAMETER => false,
|
||||
self::EVOLUTION_GRAPH_PARAMETER => false,
|
||||
self::ADDITIONAL_EMAILS_PARAMETER => false,
|
||||
self::DISPLAY_FORMAT_PARAMETER => true,
|
||||
);
|
||||
|
||||
static private $managedReportTypes = array(
|
||||
self::EMAIL_TYPE => 'plugins/Zeitgeist/images/email.png'
|
||||
);
|
||||
|
||||
static private $managedReportFormats = array(
|
||||
ReportRenderer::HTML_FORMAT => 'plugins/Zeitgeist/images/html_icon.png',
|
||||
ReportRenderer::PDF_FORMAT => 'plugins/UserSettings/images/plugins/pdf.gif',
|
||||
ReportRenderer::CSV_FORMAT => 'plugins/Morpheus/images/export.png',
|
||||
);
|
||||
|
||||
/**
|
||||
* @see Piwik\Plugin::getListHooksRegistered
|
||||
*/
|
||||
public function getListHooksRegistered()
|
||||
{
|
||||
return array(
|
||||
'Menu.Top.addItems' => 'addTopMenu',
|
||||
'TaskScheduler.getScheduledTasks' => 'getScheduledTasks',
|
||||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'MobileMessaging.deletePhoneNumber' => 'deletePhoneNumber',
|
||||
'ScheduledReports.getReportParameters' => 'getReportParameters',
|
||||
'ScheduledReports.validateReportParameters' => 'validateReportParameters',
|
||||
'ScheduledReports.getReportMetadata' => 'getReportMetadata',
|
||||
'ScheduledReports.getReportTypes' => 'getReportTypes',
|
||||
'ScheduledReports.getReportFormats' => 'getReportFormats',
|
||||
'ScheduledReports.getRendererInstance' => 'getRendererInstance',
|
||||
'ScheduledReports.getReportRecipients' => 'getReportRecipients',
|
||||
'ScheduledReports.processReports' => 'processReports',
|
||||
'ScheduledReports.allowMultipleReports' => 'allowMultipleReports',
|
||||
'ScheduledReports.sendReport' => 'sendReport',
|
||||
'Template.reportParametersScheduledReports' => 'template_reportParametersScheduledReports',
|
||||
'UsersManager.deleteUser' => 'deleteUserReport',
|
||||
'SitesManager.deleteSite.end' => 'deleteSiteReport',
|
||||
APISegmentEditor::DEACTIVATE_SEGMENT_EVENT => 'segmentDeactivation',
|
||||
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
|
||||
);
|
||||
}
|
||||
|
||||
public function getClientSideTranslationKeys(&$translationKeys)
|
||||
{
|
||||
$translationKeys[] = "ScheduledReports_ReportSent";
|
||||
$translationKeys[] = "ScheduledReports_ReportUpdated";
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete reports for the website
|
||||
*/
|
||||
public function deleteSiteReport($idSite)
|
||||
{
|
||||
$idReports = API::getInstance()->getReports($idSite);
|
||||
|
||||
foreach ($idReports as $report) {
|
||||
$idReport = $report['idreport'];
|
||||
API::getInstance()->deleteReport($idReport);
|
||||
}
|
||||
}
|
||||
|
||||
public function getJsFiles(&$jsFiles)
|
||||
{
|
||||
$jsFiles[] = "plugins/ScheduledReports/javascripts/pdf.js";
|
||||
}
|
||||
|
||||
public function validateReportParameters(&$parameters, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$reportFormat = $parameters[self::DISPLAY_FORMAT_PARAMETER];
|
||||
$availableDisplayFormats = array_keys(self::getDisplayFormats());
|
||||
if (!in_array($reportFormat, $availableDisplayFormats)) {
|
||||
throw new Exception(
|
||||
Piwik::translate(
|
||||
// General_ExceptionInvalidAggregateReportsFormat should be named General_ExceptionInvalidDisplayFormat
|
||||
'General_ExceptionInvalidAggregateReportsFormat',
|
||||
array($reportFormat, implode(', ', $availableDisplayFormats))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// emailMe is an optional parameter
|
||||
if (!isset($parameters[self::EMAIL_ME_PARAMETER])) {
|
||||
$parameters[self::EMAIL_ME_PARAMETER] = self::EMAIL_ME_PARAMETER_DEFAULT_VALUE;
|
||||
} else {
|
||||
$parameters[self::EMAIL_ME_PARAMETER] = self::valueIsTrue($parameters[self::EMAIL_ME_PARAMETER]);
|
||||
}
|
||||
|
||||
// evolutionGraph is an optional parameter
|
||||
if (!isset($parameters[self::EVOLUTION_GRAPH_PARAMETER])) {
|
||||
$parameters[self::EVOLUTION_GRAPH_PARAMETER] = self::EVOLUTION_GRAPH_PARAMETER_DEFAULT_VALUE;
|
||||
} else {
|
||||
$parameters[self::EVOLUTION_GRAPH_PARAMETER] = self::valueIsTrue($parameters[self::EVOLUTION_GRAPH_PARAMETER]);
|
||||
}
|
||||
|
||||
// additionalEmails is an optional parameter
|
||||
if (isset($parameters[self::ADDITIONAL_EMAILS_PARAMETER])) {
|
||||
$parameters[self::ADDITIONAL_EMAILS_PARAMETER] = self::checkAdditionalEmails($parameters[self::ADDITIONAL_EMAILS_PARAMETER]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// based on http://www.php.net/manual/en/filter.filters.validate.php -> FILTER_VALIDATE_BOOLEAN
|
||||
static private function valueIsTrue($value)
|
||||
{
|
||||
return $value == 'true' || $value == 1 || $value == '1' || $value === true;
|
||||
}
|
||||
|
||||
public function getReportMetadata(&$reportMetadata, $reportType, $idSite)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$availableReportMetadata = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite);
|
||||
|
||||
$filteredReportMetadata = array();
|
||||
foreach ($availableReportMetadata as $reportMetadata) {
|
||||
// removing reports from the API category and MultiSites.getOne
|
||||
if (
|
||||
$reportMetadata['category'] == 'API' ||
|
||||
$reportMetadata['category'] == Piwik::translate('General_MultiSitesSummary') && $reportMetadata['name'] == Piwik::translate('General_SingleWebsitesDashboard')
|
||||
) continue;
|
||||
|
||||
$filteredReportMetadata[] = $reportMetadata;
|
||||
}
|
||||
|
||||
$reportMetadata = $filteredReportMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportTypes(&$reportTypes)
|
||||
{
|
||||
$reportTypes = array_merge($reportTypes, self::$managedReportTypes);
|
||||
}
|
||||
|
||||
public function getReportFormats(&$reportFormats, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$reportFormats = self::$managedReportFormats;
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportParameters(&$availableParameters, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$availableParameters = self::$availableParameters;
|
||||
}
|
||||
}
|
||||
|
||||
public function processReports(&$processedReports, $reportType, $outputType, $report)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$displayFormat = $report['parameters'][self::DISPLAY_FORMAT_PARAMETER];
|
||||
$evolutionGraph = $report['parameters'][self::EVOLUTION_GRAPH_PARAMETER];
|
||||
|
||||
foreach ($processedReports as &$processedReport) {
|
||||
$metadata = $processedReport['metadata'];
|
||||
|
||||
$isAggregateReport = !empty($metadata['dimension']);
|
||||
|
||||
$processedReport['displayTable'] = $displayFormat != self::DISPLAY_FORMAT_GRAPHS_ONLY;
|
||||
|
||||
$processedReport['displayGraph'] =
|
||||
($isAggregateReport ?
|
||||
$displayFormat == self::DISPLAY_FORMAT_GRAPHS_ONLY || $displayFormat == self::DISPLAY_FORMAT_TABLES_AND_GRAPHS
|
||||
:
|
||||
$displayFormat != self::DISPLAY_FORMAT_TABLES_ONLY)
|
||||
&& \Piwik\SettingsServer::isGdExtensionEnabled()
|
||||
&& \Piwik\Plugin\Manager::getInstance()->isPluginActivated('ImageGraph')
|
||||
&& !empty($metadata['imageGraphUrl']);
|
||||
|
||||
$processedReport['evolutionGraph'] = $evolutionGraph;
|
||||
|
||||
// remove evolution metrics from MultiSites.getAll
|
||||
if ($metadata['module'] == 'MultiSites') {
|
||||
$columns = $processedReport['columns'];
|
||||
|
||||
foreach (\Piwik\Plugins\MultiSites\API::getApiMetrics($enhanced = true) as $metricSettings) {
|
||||
unset($columns[$metricSettings[\Piwik\Plugins\MultiSites\API::METRIC_EVOLUTION_COL_NAME_KEY]]);
|
||||
}
|
||||
|
||||
$processedReport['metadata'] = $metadata;
|
||||
$processedReport['columns'] = $columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getRendererInstance(&$reportRenderer, $reportType, $outputType, $report)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$reportFormat = $report['format'];
|
||||
|
||||
$reportRenderer = ReportRenderer::factory($reportFormat);
|
||||
|
||||
if ($reportFormat == ReportRenderer::HTML_FORMAT) {
|
||||
$reportRenderer->setRenderImageInline($outputType != API::OUTPUT_SAVE_ON_DISK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function allowMultipleReports(&$allowMultipleReports, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$allowMultipleReports = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function sendReport($reportType, $report, $contents, $filename, $prettyDate, $reportSubject, $reportTitle,
|
||||
$additionalFiles)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$periods = self::getPeriodToFrequencyAsAdjective();
|
||||
$message = Piwik::translate('ScheduledReports_EmailHello');
|
||||
$subject = Piwik::translate('General_Report') . ' ' . $reportTitle . " - " . $prettyDate;
|
||||
|
||||
$mail = new Mail();
|
||||
$mail->setDefaultFromPiwik();
|
||||
$mail->setSubject($subject);
|
||||
$attachmentName = $subject;
|
||||
|
||||
$displaySegmentInfo = false;
|
||||
$segmentInfo = null;
|
||||
$segment = API::getSegment($report['idsegment']);
|
||||
if ($segment != null) {
|
||||
$displaySegmentInfo = true;
|
||||
$segmentInfo = Piwik::translate('ScheduledReports_SegmentAppliedToReports', $segment['name']);
|
||||
}
|
||||
|
||||
switch ($report['format']) {
|
||||
case 'html':
|
||||
|
||||
// Needed when using images as attachment with cid
|
||||
$mail->setType(Zend_Mime::MULTIPART_RELATED);
|
||||
$message .= "<br/>" . Piwik::translate('ScheduledReports_PleaseFindBelow', array($periods[$report['period']], $reportTitle));
|
||||
|
||||
if ($displaySegmentInfo) {
|
||||
$message .= " " . $segmentInfo;
|
||||
}
|
||||
|
||||
$mail->setBodyHtml($message . "<br/><br/>" . $contents);
|
||||
break;
|
||||
|
||||
|
||||
case 'csv':
|
||||
$message .= "\n" . Piwik::translate('ScheduledReports_PleaseFindAttachedFile', array($periods[$report['period']], $reportTitle));
|
||||
|
||||
if ($displaySegmentInfo) {
|
||||
$message .= " " . $segmentInfo;
|
||||
}
|
||||
|
||||
$mail->setBodyText($message);
|
||||
$mail->createAttachment(
|
||||
$contents,
|
||||
'application/csv',
|
||||
Zend_Mime::DISPOSITION_INLINE,
|
||||
Zend_Mime::ENCODING_BASE64,
|
||||
$attachmentName . '.csv'
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'pdf':
|
||||
$message .= "\n" . Piwik::translate('ScheduledReports_PleaseFindAttachedFile', array($periods[$report['period']], $reportTitle));
|
||||
|
||||
if ($displaySegmentInfo) {
|
||||
$message .= " " . $segmentInfo;
|
||||
}
|
||||
|
||||
$mail->setBodyText($message);
|
||||
$mail->createAttachment(
|
||||
$contents,
|
||||
'application/pdf',
|
||||
Zend_Mime::DISPOSITION_INLINE,
|
||||
Zend_Mime::ENCODING_BASE64,
|
||||
$attachmentName . '.pdf'
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($additionalFiles as $additionalFile) {
|
||||
$fileContent = $additionalFile['content'];
|
||||
$at = $mail->createAttachment(
|
||||
$fileContent,
|
||||
$additionalFile['mimeType'],
|
||||
Zend_Mime::DISPOSITION_INLINE,
|
||||
$additionalFile['encoding'],
|
||||
$additionalFile['filename']
|
||||
);
|
||||
$at->id = $additionalFile['cid'];
|
||||
|
||||
unset($fileContent);
|
||||
}
|
||||
|
||||
// Get user emails and languages
|
||||
$reportParameters = $report['parameters'];
|
||||
$emails = array();
|
||||
|
||||
if (isset($reportParameters[self::ADDITIONAL_EMAILS_PARAMETER])) {
|
||||
$emails = $reportParameters[self::ADDITIONAL_EMAILS_PARAMETER];
|
||||
}
|
||||
|
||||
if ($reportParameters[self::EMAIL_ME_PARAMETER] == 1) {
|
||||
if (Piwik::getCurrentUserLogin() == $report['login']) {
|
||||
$emails[] = Piwik::getCurrentUserEmail();
|
||||
} else {
|
||||
try {
|
||||
$user = APIUsersManager::getInstance()->getUser($report['login']);
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
$emails[] = $user['email'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($emails as $email) {
|
||||
if (empty($email)) {
|
||||
continue;
|
||||
}
|
||||
$mail->addTo($email);
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
} catch (Exception $e) {
|
||||
|
||||
// If running from piwik.php with debug, we ignore the 'email not sent' error
|
||||
if (!isset($GLOBALS['PIWIK_TRACKER_DEBUG']) || !$GLOBALS['PIWIK_TRACKER_DEBUG']) {
|
||||
throw new Exception("An error occured while sending '$filename' " .
|
||||
" to " . implode(', ', $mail->getRecipients()) .
|
||||
". Error was '" . $e->getMessage() . "'");
|
||||
}
|
||||
}
|
||||
$mail->clearRecipients();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function deletePhoneNumber($phoneNumber)
|
||||
{
|
||||
$api = API::getInstance();
|
||||
|
||||
$reports = $api->getReports(
|
||||
$idSite = false,
|
||||
$period = false,
|
||||
$idReport = false,
|
||||
$ifSuperUserReturnOnlySuperUserReports = false
|
||||
);
|
||||
|
||||
foreach ($reports as $report) {
|
||||
if ($report['type'] == MobileMessaging::MOBILE_TYPE) {
|
||||
$reportParameters = $report['parameters'];
|
||||
$reportPhoneNumbers = $reportParameters[MobileMessaging::PHONE_NUMBERS_PARAMETER];
|
||||
$updatedPhoneNumbers = array();
|
||||
foreach ($reportPhoneNumbers as $reportPhoneNumber) {
|
||||
if ($reportPhoneNumber != $phoneNumber) {
|
||||
$updatedPhoneNumbers[] = $reportPhoneNumber;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($updatedPhoneNumbers) != count($reportPhoneNumbers)) {
|
||||
$reportParameters[MobileMessaging::PHONE_NUMBERS_PARAMETER] = $updatedPhoneNumbers;
|
||||
|
||||
// note: reports can end up without any recipients
|
||||
$api->updateReport(
|
||||
$report['idreport'],
|
||||
$report['idsite'],
|
||||
$report['description'],
|
||||
$report['period'],
|
||||
$report['hour'],
|
||||
$report['type'],
|
||||
$report['format'],
|
||||
$report['reports'],
|
||||
$reportParameters
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportRecipients(&$recipients, $reportType, $report)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$parameters = $report['parameters'];
|
||||
$eMailMe = $parameters[self::EMAIL_ME_PARAMETER];
|
||||
|
||||
if ($eMailMe) {
|
||||
$recipients[] = Piwik::getCurrentUserEmail();
|
||||
}
|
||||
|
||||
if (isset($parameters[self::ADDITIONAL_EMAILS_PARAMETER])) {
|
||||
$additionalEMails = $parameters[self::ADDITIONAL_EMAILS_PARAMETER];
|
||||
$recipients = array_merge($recipients, $additionalEMails);
|
||||
}
|
||||
$recipients = array_filter($recipients);
|
||||
}
|
||||
}
|
||||
|
||||
static public function template_reportParametersScheduledReports(&$out)
|
||||
{
|
||||
$view = new View('@ScheduledReports/reportParametersScheduledReports');
|
||||
$view->currentUserEmail = Piwik::getCurrentUserEmail();
|
||||
$view->reportType = self::EMAIL_TYPE;
|
||||
$view->defaultDisplayFormat = self::DEFAULT_DISPLAY_FORMAT;
|
||||
$view->defaultEmailMe = self::EMAIL_ME_PARAMETER_DEFAULT_VALUE ? 'true' : 'false';
|
||||
$view->defaultEvolutionGraph = self::EVOLUTION_GRAPH_PARAMETER_DEFAULT_VALUE ? 'true' : 'false';
|
||||
$out .= $view->render();
|
||||
}
|
||||
|
||||
private static function manageEvent($reportType)
|
||||
{
|
||||
return in_array($reportType, array_keys(self::$managedReportTypes));
|
||||
}
|
||||
|
||||
public function getScheduledTasks(&$tasks)
|
||||
{
|
||||
foreach (API::getInstance()->getReports() as $report) {
|
||||
if (!$report['deleted'] && $report['period'] != ScheduledTime::PERIOD_NEVER) {
|
||||
|
||||
$timezone = Site::getTimezoneFor($report['idsite']);
|
||||
|
||||
$schedule = ScheduledTime::getScheduledTimeForPeriod($report['period']);
|
||||
$schedule->setHour($report['hour']);
|
||||
$schedule->setTimezone($timezone);
|
||||
$tasks[] = new ScheduledTask (
|
||||
API::getInstance(),
|
||||
'sendReport',
|
||||
$report['idreport'], $schedule
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function segmentDeactivation($idSegment)
|
||||
{
|
||||
$reportsUsingSegment = API::getInstance()->getReports(false, false, false, false, $idSegment);
|
||||
|
||||
if (count($reportsUsingSegment) > 0) {
|
||||
|
||||
$reportList = '';
|
||||
$reportNameJoinText = ' ' . Piwik::translate('General_And') . ' ';
|
||||
foreach ($reportsUsingSegment as $report) {
|
||||
$reportList .= '\'' . $report['description'] . '\'' . $reportNameJoinText;
|
||||
}
|
||||
$reportList = rtrim($reportList, $reportNameJoinText);
|
||||
|
||||
$errorMessage = Piwik::translate('ScheduledReports_Segment_Deletion_Error', $reportList);
|
||||
throw new Exception($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function addTopMenu()
|
||||
{
|
||||
MenuTop::addEntry(
|
||||
$this->getTopMenuTranslationKey(),
|
||||
array('module' => 'ScheduledReports', 'action' => 'index', 'segment' => false),
|
||||
true,
|
||||
13,
|
||||
$isHTML = false,
|
||||
$tooltip = Piwik::translate(
|
||||
\Piwik\Plugin\Manager::getInstance()->isPluginActivated('MobileMessaging')
|
||||
? 'MobileMessaging_TopLinkTooltip' : 'ScheduledReports_TopLinkTooltip'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getTopMenuTranslationKey()
|
||||
{
|
||||
// if MobileMessaging is not activated, display 'Email reports'
|
||||
if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('MobileMessaging'))
|
||||
return self::PDF_REPORTS_TOP_MENU_TRANSLATION_KEY;
|
||||
|
||||
if (Piwik::isUserIsAnonymous()) {
|
||||
return self::MOBILE_MESSAGING_TOP_MENU_TRANSLATION_KEY;
|
||||
}
|
||||
|
||||
$reports = API::getInstance()->getReports();
|
||||
$reportCount = count($reports);
|
||||
|
||||
// if there are no reports and the mobile account is
|
||||
// not configured, display 'Email reports'
|
||||
// configured, display 'Email & SMS reports'
|
||||
if ($reportCount == 0)
|
||||
return APIMobileMessaging::getInstance()->areSMSAPICredentialProvided() ?
|
||||
self::MOBILE_MESSAGING_TOP_MENU_TRANSLATION_KEY : self::PDF_REPORTS_TOP_MENU_TRANSLATION_KEY;
|
||||
|
||||
$anyMobileReport = false;
|
||||
foreach ($reports as $report) {
|
||||
if ($report['type'] == MobileMessaging::MOBILE_TYPE) {
|
||||
$anyMobileReport = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is at least one sms report, display 'Email & SMS reports'
|
||||
if ($anyMobileReport) {
|
||||
return self::MOBILE_MESSAGING_TOP_MENU_TRANSLATION_KEY;
|
||||
}
|
||||
|
||||
return self::PDF_REPORTS_TOP_MENU_TRANSLATION_KEY;
|
||||
}
|
||||
|
||||
public function deleteUserReport($userLogin)
|
||||
{
|
||||
Db::query('DELETE FROM ' . Common::prefixTable('report') . ' WHERE login = ?', $userLogin);
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
$reportTable = "`idreport` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`idsite` INTEGER(11) NOT NULL,
|
||||
`login` VARCHAR(100) NOT NULL,
|
||||
`description` VARCHAR(255) NOT NULL,
|
||||
`idsegment` INT(11),
|
||||
`period` VARCHAR(10) NOT NULL,
|
||||
`hour` tinyint NOT NULL default 0,
|
||||
`type` VARCHAR(10) NOT NULL,
|
||||
`format` VARCHAR(10) NOT NULL,
|
||||
`reports` TEXT NOT NULL,
|
||||
`parameters` TEXT NULL,
|
||||
`ts_created` TIMESTAMP NULL,
|
||||
`ts_last_sent` TIMESTAMP NULL,
|
||||
`deleted` tinyint(4) NOT NULL default 0,
|
||||
PRIMARY KEY (`idreport`)";
|
||||
|
||||
DbHelper::createTable('report', $reportTable);
|
||||
}
|
||||
|
||||
private static function checkAdditionalEmails($additionalEmails)
|
||||
{
|
||||
foreach ($additionalEmails as &$email) {
|
||||
$email = trim($email);
|
||||
if (empty($email)) {
|
||||
$email = false;
|
||||
} elseif (!Piwik::isValidEmailString($email)) {
|
||||
throw new Exception(Piwik::translate('UsersManager_ExceptionInvalidEmail') . ' (' . $email . ')');
|
||||
}
|
||||
}
|
||||
$additionalEmails = array_filter($additionalEmails);
|
||||
return $additionalEmails;
|
||||
}
|
||||
|
||||
public static function getDisplayFormats()
|
||||
{
|
||||
$displayFormats = array(
|
||||
// ScheduledReports_AggregateReportsFormat_TablesOnly should be named ScheduledReports_DisplayFormat_GraphsOnlyForKeyMetrics
|
||||
self::DISPLAY_FORMAT_GRAPHS_ONLY_FOR_KEY_METRICS => Piwik::translate('ScheduledReports_AggregateReportsFormat_TablesOnly'),
|
||||
// ScheduledReports_AggregateReportsFormat_GraphsOnly should be named ScheduledReports_DisplayFormat_GraphsOnly
|
||||
self::DISPLAY_FORMAT_GRAPHS_ONLY => Piwik::translate('ScheduledReports_AggregateReportsFormat_GraphsOnly'),
|
||||
// ScheduledReports_AggregateReportsFormat_TablesAndGraphs should be named ScheduledReports_DisplayFormat_TablesAndGraphs
|
||||
self::DISPLAY_FORMAT_TABLES_AND_GRAPHS => Piwik::translate('ScheduledReports_AggregateReportsFormat_TablesAndGraphs'),
|
||||
self::DISPLAY_FORMAT_TABLES_ONLY => Piwik::translate('ScheduledReports_DisplayFormat_TablesOnly'),
|
||||
);
|
||||
return $displayFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the Report Listing
|
||||
* @ignore
|
||||
*/
|
||||
static public function getPeriodToFrequency()
|
||||
{
|
||||
return array(
|
||||
ScheduledTime::PERIOD_NEVER => Piwik::translate('General_Never'),
|
||||
ScheduledTime::PERIOD_DAY => Piwik::translate('General_Daily'),
|
||||
ScheduledTime::PERIOD_WEEK => Piwik::translate('General_Weekly'),
|
||||
ScheduledTime::PERIOD_MONTH => Piwik::translate('General_Monthly'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in the Report's email content, ie "monthly report"
|
||||
* @ignore
|
||||
*/
|
||||
static public function getPeriodToFrequencyAsAdjective()
|
||||
{
|
||||
return array(
|
||||
ScheduledTime::PERIOD_DAY => Piwik::translate('General_DailyReport'),
|
||||
ScheduledTime::PERIOD_WEEK => Piwik::translate('General_WeeklyReport'),
|
||||
ScheduledTime::PERIOD_MONTH => Piwik::translate('General_MonthlyReport'),
|
||||
ScheduledTime::PERIOD_YEAR => Piwik::translate('General_YearlyReport'),
|
||||
ScheduledTime::PERIOD_RANGE => Piwik::translate('General_RangeReports'),
|
||||
);
|
||||
}
|
||||
}
|
||||
245
www/analytics/plugins/ScheduledReports/config/tcpdf_config.php
Normal file
245
www/analytics/plugins/ScheduledReports/config/tcpdf_config.php
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Override settings in libs/tcpdf_config.php
|
||||
*
|
||||
*/
|
||||
|
||||
define('K_PATH_MAIN', PIWIK_INCLUDE_PATH . '/libs/tcpdf/');
|
||||
|
||||
$pathTmpTCPDF = PIWIK_USER_PATH . '/tmp/tcpdf/';
|
||||
$pathTmpTCPDF = \Piwik\SettingsPiwik::rewriteTmpPathWithHostname($pathTmpTCPDF);
|
||||
|
||||
define('K_PATH_CACHE', $pathTmpTCPDF);
|
||||
define('K_PATH_IMAGES', $pathTmpTCPDF);
|
||||
|
||||
if (!defined('K_TCPDF_EXTERNAL_CONFIG')) {
|
||||
|
||||
// DOCUMENT_ROOT fix for IIS Webserver
|
||||
if ((!isset($_SERVER['DOCUMENT_ROOT'])) OR (empty($_SERVER['DOCUMENT_ROOT']))) {
|
||||
if (isset($_SERVER['SCRIPT_FILENAME'])) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF'])));
|
||||
} elseif (isset($_SERVER['PATH_TRANSLATED'])) {
|
||||
$_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF'])));
|
||||
} else {
|
||||
// define here your DOCUMENT_ROOT path if the previous fails
|
||||
$_SERVER['DOCUMENT_ROOT'] = '/var/www';
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined('K_PATH_MAIN')) {
|
||||
// Automatic calculation for the following K_PATH_MAIN constant
|
||||
$k_path_main = str_replace('\\', '/', realpath(substr(dirname(__FILE__), 0, 0 - strlen('config'))));
|
||||
if (substr($k_path_main, -1) != '/') {
|
||||
$k_path_main .= '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Installation path (/var/www/tcpdf/).
|
||||
* By default it is automatically calculated but you can also set it as a fixed string to improve performances.
|
||||
*/
|
||||
if (!defined('K_PATH_MAIN')) {
|
||||
define ('K_PATH_MAIN', $k_path_main);
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined('K_PATH_URL')) {
|
||||
// Automatic calculation for the following K_PATH_URL constant
|
||||
$k_path_url = K_PATH_MAIN; // default value for console mode
|
||||
if (isset($_SERVER['HTTP_HOST']) AND (!empty($_SERVER['HTTP_HOST']))) {
|
||||
if (isset($_SERVER['HTTPS']) AND (!empty($_SERVER['HTTPS'])) AND strtolower($_SERVER['HTTPS']) != 'off') {
|
||||
$k_path_url = 'https://';
|
||||
} else {
|
||||
$k_path_url = 'http://';
|
||||
}
|
||||
$k_path_url .= $_SERVER['HTTP_HOST'];
|
||||
$k_path_url .= str_replace('\\', '/', substr(K_PATH_MAIN, (strlen($_SERVER['DOCUMENT_ROOT']) - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* URL path to tcpdf installation folder (http://localhost/tcpdf/).
|
||||
* By default it is automatically calculated but you can also set it as a fixed string to improve performances.
|
||||
*/
|
||||
define ('K_PATH_URL', $k_path_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* path for PDF fonts
|
||||
* use K_PATH_MAIN.'fonts/old/' for old non-UTF8 fonts
|
||||
*/
|
||||
define ('K_PATH_FONTS', K_PATH_MAIN . 'fonts/');
|
||||
|
||||
/**
|
||||
* cache directory for temporary files (full path)
|
||||
*/
|
||||
if (!defined('K_PATH_CACHE')) {
|
||||
define ('K_PATH_CACHE', K_PATH_MAIN . 'cache/');
|
||||
}
|
||||
|
||||
/**
|
||||
* cache directory for temporary files (url path)
|
||||
*/
|
||||
define ('K_PATH_URL_CACHE', K_PATH_URL . 'cache/');
|
||||
|
||||
/**
|
||||
*images directory
|
||||
*/
|
||||
if (!defined('K_PATH_IMAGES')) {
|
||||
define ('K_PATH_IMAGES', K_PATH_MAIN . 'images/');
|
||||
}
|
||||
|
||||
/**
|
||||
* blank image
|
||||
*/
|
||||
define ('K_BLANK_IMAGE', K_PATH_IMAGES . '_blank.png');
|
||||
|
||||
/**
|
||||
* page format
|
||||
*/
|
||||
define ('PDF_PAGE_FORMAT', 'A4');
|
||||
|
||||
/**
|
||||
* page orientation (P=portrait, L=landscape)
|
||||
*/
|
||||
define ('PDF_PAGE_ORIENTATION', 'P');
|
||||
|
||||
/**
|
||||
* document creator
|
||||
*/
|
||||
define ('PDF_CREATOR', 'TCPDF');
|
||||
|
||||
/**
|
||||
* document author
|
||||
*/
|
||||
define ('PDF_AUTHOR', 'TCPDF');
|
||||
|
||||
/**
|
||||
* header title
|
||||
*/
|
||||
define ('PDF_HEADER_TITLE', 'TCPDF Example');
|
||||
|
||||
/**
|
||||
* header description string
|
||||
*/
|
||||
define ('PDF_HEADER_STRING', "by Nicola Asuni - Tecnick.com\nwww.tcpdf.org");
|
||||
|
||||
/**
|
||||
* image logo
|
||||
*/
|
||||
define ('PDF_HEADER_LOGO', 'tcpdf_logo.jpg');
|
||||
|
||||
/**
|
||||
* header logo image width [mm]
|
||||
*/
|
||||
define ('PDF_HEADER_LOGO_WIDTH', 30);
|
||||
|
||||
/**
|
||||
* document unit of measure [pt=point, mm=millimeter, cm=centimeter, in=inch]
|
||||
*/
|
||||
define ('PDF_UNIT', 'mm');
|
||||
|
||||
/**
|
||||
* header margin
|
||||
*/
|
||||
define ('PDF_MARGIN_HEADER', 5);
|
||||
|
||||
/**
|
||||
* footer margin
|
||||
*/
|
||||
define ('PDF_MARGIN_FOOTER', 10);
|
||||
|
||||
/**
|
||||
* top margin
|
||||
*/
|
||||
define ('PDF_MARGIN_TOP', 27);
|
||||
|
||||
/**
|
||||
* bottom margin
|
||||
*/
|
||||
define ('PDF_MARGIN_BOTTOM', 25);
|
||||
|
||||
/**
|
||||
* left margin
|
||||
*/
|
||||
define ('PDF_MARGIN_LEFT', 15);
|
||||
|
||||
/**
|
||||
* right margin
|
||||
*/
|
||||
define ('PDF_MARGIN_RIGHT', 15);
|
||||
|
||||
/**
|
||||
* default main font name
|
||||
*/
|
||||
define ('PDF_FONT_NAME_MAIN', 'helvetica');
|
||||
|
||||
/**
|
||||
* default main font size
|
||||
*/
|
||||
define ('PDF_FONT_SIZE_MAIN', 10);
|
||||
|
||||
/**
|
||||
* default data font name
|
||||
*/
|
||||
define ('PDF_FONT_NAME_DATA', 'helvetica');
|
||||
|
||||
/**
|
||||
* default data font size
|
||||
*/
|
||||
define ('PDF_FONT_SIZE_DATA', 8);
|
||||
|
||||
/**
|
||||
* default monospaced font name
|
||||
*/
|
||||
define ('PDF_FONT_MONOSPACED', 'courier');
|
||||
|
||||
/**
|
||||
* ratio used to adjust the conversion of pixels to user units
|
||||
*/
|
||||
define ('PDF_IMAGE_SCALE_RATIO', 1.25);
|
||||
|
||||
/**
|
||||
* magnification factor for titles
|
||||
*/
|
||||
define('HEAD_MAGNIFICATION', 1.1);
|
||||
|
||||
/**
|
||||
* height of cell repect font height
|
||||
*/
|
||||
define('K_CELL_HEIGHT_RATIO', 1.25);
|
||||
|
||||
/**
|
||||
* title magnification respect main font size
|
||||
*/
|
||||
define('K_TITLE_MAGNIFICATION', 1.3);
|
||||
|
||||
/**
|
||||
* reduction factor for small font
|
||||
*/
|
||||
define('K_SMALL_RATIO', 2 / 3);
|
||||
|
||||
/**
|
||||
* set to true to enable the special procedure used to avoid the overlappind of symbols on Thai language
|
||||
*/
|
||||
define('K_THAI_TOPCHARS', true);
|
||||
|
||||
/**
|
||||
* if true allows to call TCPDF methods using HTML syntax
|
||||
* IMPORTANT: For security reason, disable this feature if you are printing user HTML content.
|
||||
*/
|
||||
define('K_TCPDF_CALLS_IN_HTML', true);
|
||||
}
|
||||
|
||||
// define the constant K_TCPDF_EXTERNAL_CONFIG to ignore tcpdf's default settings
|
||||
define('K_TCPDF_EXTERNAL_CONFIG', true);
|
||||
|
||||
//============================================================+
|
||||
// END OF FILE
|
||||
//============================================================+
|
||||
202
www/analytics/plugins/ScheduledReports/javascripts/pdf.js
Normal file
202
www/analytics/plugins/ScheduledReports/javascripts/pdf.js
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
var getReportParametersFunctions = Object();
|
||||
var updateReportParametersFunctions = Object();
|
||||
var resetReportParametersFunctions = Object();
|
||||
|
||||
function formSetEditReport(idReport) {
|
||||
var report = {
|
||||
'type': ReportPlugin.defaultReportType,
|
||||
'format': ReportPlugin.defaultReportFormat,
|
||||
'description': '',
|
||||
'period': ReportPlugin.defaultPeriod,
|
||||
'hour': ReportPlugin.defaultHour,
|
||||
'reports': []
|
||||
};
|
||||
|
||||
if (idReport > 0) {
|
||||
report = ReportPlugin.reportList[idReport];
|
||||
$('#report_submit').val(ReportPlugin.updateReportString);
|
||||
}
|
||||
else {
|
||||
$('#report_submit').val(ReportPlugin.createReportString);
|
||||
}
|
||||
|
||||
toggleReportType(report.type);
|
||||
|
||||
$('#report_description').html(report.description);
|
||||
$('#report_segment').find('option[value=' + report.idsegment + ']').prop('selected', 'selected');
|
||||
$('#report_type').find('option[value=' + report.type + ']').prop('selected', 'selected');
|
||||
$('#report_period').find('option[value=' + report.period + ']').prop('selected', 'selected');
|
||||
$('#report_hour').val(report.hour);
|
||||
$('[name=report_format].' + report.type + ' option[value=' + report.format + ']').prop('selected', 'selected');
|
||||
|
||||
var selectorReportFormat = 'select[name=report_format].' + $('#report_type').val();
|
||||
$(selectorReportFormat).change( toggleDisplayOptionsByFormat );
|
||||
|
||||
// When CSV is selected, hide "Display options"
|
||||
toggleDisplayOptionsByFormat();
|
||||
|
||||
function toggleDisplayOptionsByFormat() {
|
||||
var format = $(selectorReportFormat).val();
|
||||
var displayOptionsSelector = $('#row_report_display_options');
|
||||
if (format == 'csv') {
|
||||
displayOptionsSelector.hide();
|
||||
} else {
|
||||
displayOptionsSelector.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('[name=reportsList] input').prop('checked', false);
|
||||
|
||||
var key;
|
||||
for (key in report.reports) {
|
||||
$('.' + report.type + ' [report-unique-id=' + report.reports[key] + ']').prop('checked', 'checked');
|
||||
}
|
||||
|
||||
updateReportParametersFunctions[report.type](report.parameters);
|
||||
|
||||
$('#report_idreport').val(idReport);
|
||||
}
|
||||
|
||||
function getReportAjaxRequest(idReport, defaultApiMethod) {
|
||||
var parameters = {};
|
||||
piwikHelper.lazyScrollTo(".centerLargeDiv>h2", 400);
|
||||
parameters.module = 'API';
|
||||
parameters.method = defaultApiMethod;
|
||||
if (idReport == 0) {
|
||||
parameters.method = 'ScheduledReports.addReport';
|
||||
}
|
||||
parameters.format = 'json';
|
||||
return parameters;
|
||||
}
|
||||
|
||||
function toggleReportType(reportType) {
|
||||
resetReportParametersFunctions[reportType]();
|
||||
$('#report_type').find('option').each(function (index, type) {
|
||||
$('.' + $(type).val()).hide();
|
||||
});
|
||||
$('.' + reportType).show();
|
||||
}
|
||||
|
||||
function fadeInOutSuccessMessage(selector, message) {
|
||||
|
||||
var UI = require('piwik/UI');
|
||||
var notification = new UI.Notification();
|
||||
notification.show(message, {
|
||||
placeat: selector,
|
||||
context: 'success',
|
||||
noclear: true,
|
||||
type: 'toast',
|
||||
style: {display: 'inline-block', marginTop: '10px'},
|
||||
id: 'usersManagerAccessUpdated'
|
||||
});
|
||||
|
||||
piwikHelper.refreshAfter(2);
|
||||
}
|
||||
|
||||
function initManagePdf() {
|
||||
// Click Add/Update Submit
|
||||
$('#addEditReport').submit(function () {
|
||||
var idReport = $('#report_idreport').val();
|
||||
var apiParameters = getReportAjaxRequest(idReport, 'ScheduledReports.updateReport');
|
||||
apiParameters.idReport = idReport;
|
||||
apiParameters.description = $('#report_description').val();
|
||||
apiParameters.idSegment = $('#report_segment').find('option:selected').val();
|
||||
apiParameters.reportType = $('#report_type').find('option:selected').val();
|
||||
apiParameters.reportFormat = $('[name=report_format].' + apiParameters.reportType + ' option:selected').val();
|
||||
|
||||
var reports = [];
|
||||
$('[name=reportsList].' + apiParameters.reportType + ' input:checked').each(function () {
|
||||
reports.push($(this).attr('report-unique-id'));
|
||||
});
|
||||
if (reports.length > 0) {
|
||||
apiParameters.reports = reports;
|
||||
}
|
||||
|
||||
apiParameters.parameters = getReportParametersFunctions[apiParameters.reportType]();
|
||||
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams(apiParameters, 'POST');
|
||||
ajaxHandler.addParams({period: $('#report_period').find('option:selected').val()}, 'GET');
|
||||
ajaxHandler.addParams({hour: $('#report_hour').val()}, 'GET');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement();
|
||||
if (idReport) {
|
||||
ajaxHandler.setCallback(function (response) {
|
||||
|
||||
fadeInOutSuccessMessage('#reportUpdatedSuccess', _pk_translate('ScheduledReports_ReportUpdated'));
|
||||
});
|
||||
}
|
||||
ajaxHandler.send(true);
|
||||
return false;
|
||||
});
|
||||
|
||||
// Email now
|
||||
$('a[name=linkSendNow]').click(function () {
|
||||
var idReport = $(this).attr('idreport');
|
||||
var parameters = getReportAjaxRequest(idReport, 'ScheduledReports.sendReport');
|
||||
parameters.idReport = idReport;
|
||||
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams(parameters, 'POST');
|
||||
ajaxHandler.setLoadingElement();
|
||||
ajaxHandler.setCallback(function (response) {
|
||||
fadeInOutSuccessMessage('#reportSentSuccess', _pk_translate('ScheduledReports_ReportSent'));
|
||||
});
|
||||
ajaxHandler.send(true);
|
||||
});
|
||||
|
||||
// Delete Report
|
||||
$('a[name=linkDeleteReport]').click(function () {
|
||||
var idReport = $(this).attr('id');
|
||||
|
||||
function onDelete() {
|
||||
var parameters = getReportAjaxRequest(idReport, 'ScheduledReports.deleteReport');
|
||||
parameters.idReport = idReport;
|
||||
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams(parameters, 'POST');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement();
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
|
||||
piwikHelper.modalConfirm('#confirm', {yes: onDelete});
|
||||
});
|
||||
|
||||
// Edit Report click
|
||||
$('a[name=linkEditReport]').click(function () {
|
||||
var idReport = $(this).attr('id');
|
||||
formSetEditReport(idReport);
|
||||
$('.entityAddContainer').show();
|
||||
$('#entityEditContainer').hide();
|
||||
$(document).trigger('ScheduledReport.edit', {});
|
||||
});
|
||||
|
||||
// Switch Report Type
|
||||
$('#report_type').change(function () {
|
||||
var reportType = $(this).val();
|
||||
toggleReportType(reportType);
|
||||
});
|
||||
|
||||
// Add a Report click
|
||||
$('#linkAddReport').click(function () {
|
||||
$('.entityAddContainer').show();
|
||||
$('#entityEditContainer').hide();
|
||||
formSetEditReport(/*idReport = */0);
|
||||
});
|
||||
|
||||
// Cancel click
|
||||
$('.entityCancelLink').click(function () {
|
||||
$('.entityAddContainer').hide();
|
||||
$('#entityEditContainer').show();
|
||||
piwikHelper.hideAjaxError();
|
||||
}).click();
|
||||
}
|
||||
181
www/analytics/plugins/ScheduledReports/templates/_addReport.twig
Normal file
181
www/analytics/plugins/ScheduledReports/templates/_addReport.twig
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<div class="entityAddContainer" style="display:none;">
|
||||
<div class='entityCancel'>
|
||||
{{ 'ScheduledReports_CancelAndReturnToReports'|translate("<a class='entityCancelLink'>","</a>")|raw }}
|
||||
</div>
|
||||
<div class='clear'></div>
|
||||
<form id='addEditReport'>
|
||||
<table class="dataTable entityTable">
|
||||
<thead>
|
||||
<tr class="first">
|
||||
<th colspan="2">{{ 'ScheduledReports_CreateAndScheduleReport'|translate }}</th>
|
||||
<tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="first">{{ 'General_Website'|translate }} </td>
|
||||
<td style="width:650px;">
|
||||
{{ siteName|raw }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="first">{{ 'General_Description'|translate }} </td>
|
||||
<td>
|
||||
<textarea cols="30" rows="3" id="report_description" class="inp"></textarea>
|
||||
|
||||
<div class="entityInlineHelp">
|
||||
{{ 'ScheduledReports_DescriptionOnFirstPage'|translate }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% if segmentEditorActivated %}
|
||||
<tr>
|
||||
<td class="first">{{ 'SegmentEditor_ChooseASegment'|translate }} </td>
|
||||
<td>
|
||||
<select id='report_segment'>
|
||||
<option value="">{{ 'SegmentEditor_DefaultAllVisits'|translate }}</option>
|
||||
{% for savedSegmentId, savedSegmentName in savedSegmentsById %}
|
||||
<option value="{{ savedSegmentId }}">{{ savedSegmentName[:50] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<div class="entityInlineHelp">
|
||||
{% set SegmentEditor_DefaultAllVisits %}{{ 'SegmentEditor_DefaultAllVisits'|translate }}{% endset %}
|
||||
{% set SegmentEditor_AddNewSegment %}{{ 'SegmentEditor_AddNewSegment'|translate }}{% endset %}
|
||||
{{ 'ScheduledReports_Segment_Help'|translate('<a href="./" target="_blank">','</a>',SegmentEditor_DefaultAllVisits,SegmentEditor_AddNewSegment)|raw }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td class="first">{{ 'ScheduledReports_EmailSchedule'|translate }}</td>
|
||||
<td>
|
||||
<select id="report_period" class="inp">
|
||||
{% for periodId, period in periods %}
|
||||
<option value="{{ periodId }}">
|
||||
{{ period }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<div class="entityInlineHelp">
|
||||
{{ 'ScheduledReports_WeeklyScheduleHelp'|translate }}
|
||||
<br/>
|
||||
{{ 'ScheduledReports_MonthlyScheduleHelp'|translate }}
|
||||
<br/>
|
||||
{{ 'ScheduledReports_ReportHour'|translate }}
|
||||
<input type="text" style="height: 0.9em;padding-left: 5px;width: 35px;" id="report_hour" class="inp" size="2">
|
||||
{{ 'ScheduledReports_OClock'|translate }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr {% if reportTypes|length == 1 %}style="display:none;"{% endif %}>
|
||||
<td class="first">
|
||||
{{ 'ScheduledReports_ReportType'|translate }}
|
||||
</td>
|
||||
<td>
|
||||
<select id="report_type">
|
||||
{% for reportType, reportTypeIcon in reportTypes %}
|
||||
<option value="{{ reportType }}">{{ reportType|upper }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="first">
|
||||
{{ 'ScheduledReports_ReportFormat'|translate }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
{% for reportType, reportFormats in reportFormatsByReportType %}
|
||||
<select name='report_format' class='{{ reportType }}'>
|
||||
{% for reportFormat, reportFormatIcon in reportFormats %}
|
||||
<option value="{{ reportFormat }}">{{ reportFormat|upper }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{ postEvent("Template.reportParametersScheduledReports") }}
|
||||
|
||||
<tr id="row_report_display_options">
|
||||
<td class="first">
|
||||
{# ScheduledReports_AggregateReportsFormat should be named ScheduledReports_DisplayFormat #}
|
||||
{{ 'ScheduledReports_AggregateReportsFormat'|translate }}
|
||||
</td>
|
||||
<td>
|
||||
<select id="display_format">
|
||||
{% for formatValue, formatLabel in displayFormats %}
|
||||
<option {% if formatValue==1 %}selected{% endif %} value="{{ formatValue }}">{{ formatLabel }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<div class='report_evolution_graph'>
|
||||
<br/>
|
||||
<input type="checkbox" id="report_evolution_graph"/>
|
||||
<label for="report_evolution_graph"><em>{{ 'ScheduledReports_EvolutionGraph'|translate(5) }}</em></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="first">{{ 'ScheduledReports_ReportsIncluded'|translate }}</td>
|
||||
<td>
|
||||
{% for reportType, reportsByCategory in reportsByCategoryByReportType %}
|
||||
<div name='reportsList' class='{{ reportType }}'>
|
||||
|
||||
{% if allowMultipleReportsByReportType[reportType] %}
|
||||
{% set reportInputType='checkbox' %}
|
||||
{% else %}
|
||||
{% set reportInputType='radio' %}
|
||||
{% endif %}
|
||||
|
||||
{% set countCategory=0 %}
|
||||
|
||||
{% set newColumnAfter=(reportsByCategory|length + 1)//2 %}
|
||||
|
||||
<div id='leftcolumn'>
|
||||
{% for category, reports in reportsByCategory %}
|
||||
{% if countCategory >= newColumnAfter and newColumnAfter != 0 %}
|
||||
{% set newColumnAfter=0 %}
|
||||
</div>
|
||||
<div id='rightcolumn'>
|
||||
{% endif %}
|
||||
<div class='reportCategory'>{{ category }}</div>
|
||||
<ul class='listReports'>
|
||||
{% for report in reports %}
|
||||
<li>
|
||||
<input type='{{ reportInputType }}' id="{{ reportType }}{{ report.uniqueId }}" report-unique-id='{{ report.uniqueId }}'
|
||||
name='{{ reportType }}Reports'/>
|
||||
<label for="{{ reportType }}{{ report.uniqueId }}">
|
||||
{{ report.name|raw }}
|
||||
{% if report.uniqueId=='MultiSites_getAll' %}
|
||||
<div class="entityInlineHelp">{{ 'ScheduledReports_ReportIncludeNWebsites'|translate(countWebsites)
|
||||
}}</div>
|
||||
{% endif %}
|
||||
</label>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% set countCategory=countCategory+1 %}
|
||||
</ul>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<input type="hidden" id="report_idreport" value="">
|
||||
<input type="submit" id="report_submit" name="submit" class="submit"/>
|
||||
|
||||
</form>
|
||||
<div class='entityCancel'>
|
||||
{{ 'General_OrCancel'|translate("<a class='entityCancelLink'>","</a>")|raw }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<div id='entityEditContainer'>
|
||||
<table class="dataTable entityTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="first">{{ 'General_Description'|translate }}</th>
|
||||
<th>{{ 'ScheduledReports_EmailSchedule'|translate }}</th>
|
||||
<th>{{ 'ScheduledReports_ReportFormat'|translate }}</th>
|
||||
<th>{{ 'ScheduledReports_SendReportTo'|translate }}</th>
|
||||
<th>{{ 'General_Download'|translate }}</th>
|
||||
<th>{{ 'General_Edit'|translate }}</th>
|
||||
<th>{{ 'General_Delete'|translate }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
{% if userLogin == 'anonymous' %}
|
||||
<tr>
|
||||
<td colspan='7'>
|
||||
<br/>
|
||||
{{ 'ScheduledReports_MustBeLoggedIn'|translate }}
|
||||
<br/>› <a href='index.php?module={{ loginModule }}'>{{ 'Login_LogIn'|translate }}</a>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% elseif reports is empty %}
|
||||
<tr>
|
||||
<td colspan='7'>
|
||||
<br/>
|
||||
{{ 'ScheduledReports_ThereIsNoReportToManage'|translate(siteName)|raw }}.
|
||||
<br/><br/>
|
||||
<a onclick='' id='linkAddReport'>› {{ 'ScheduledReports_CreateAndScheduleReport'|translate }}</a>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% else %}
|
||||
{% for report in reports %}
|
||||
<tr>
|
||||
<td class="first">
|
||||
{{ report.description | raw }}
|
||||
{% if segmentEditorActivated and report.idsegment %}
|
||||
<div class="entityInlineHelp" style="font-size: 9pt;">
|
||||
{{ savedSegmentsById[report.idsegment] }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ periods[report.period] }}
|
||||
<!-- Last sent on {{ report.ts_last_sent }} -->
|
||||
</td>
|
||||
<td>
|
||||
{% if report.format is not empty %}
|
||||
{{ report.format|upper }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{# report recipients #}
|
||||
{% if report.recipients|length == 0 %}
|
||||
{{ 'ScheduledReports_NoRecipients'|translate }}
|
||||
{% else %}
|
||||
{% for recipient in report.recipients %}
|
||||
{{ recipient }}
|
||||
<br/>
|
||||
{% endfor %}
|
||||
{# send now link #}
|
||||
<a href="#" idreport="{{ report.idreport }}" name="linkSendNow" class="link_but" style="margin-top:3px;">
|
||||
<img border=0 src='{{ reportTypes[report.type] }}'/>
|
||||
{{ 'ScheduledReports_SendReportNow'|translate }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{# download link #}
|
||||
<a href="{{ linkTo({'module':'API', 'segment': null, 'token_auth':token_auth, 'method':'ScheduledReports.generateReport', 'idReport':report.idreport, 'outputType':downloadOutputType, 'language':language}) }}"
|
||||
target="_blank" name="linkDownloadReport" id="{{ report.idreport }}" class="link_but">
|
||||
<img src='{{ reportFormatsByReportType[report.type][report.format] }}' border="0"/>
|
||||
{{ 'General_Download'|translate }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{# edit link #}
|
||||
<a href='#' name="linkEditReport" id="{{ report.idreport }}" class="link_but">
|
||||
<img src='plugins/Zeitgeist/images/ico_edit.png' border="0"/>
|
||||
{{ 'General_Edit'|translate }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{# delete link #}
|
||||
<a href='#' name="linkDeleteReport" id="{{ report.idreport }}" class="link_but">
|
||||
<img src='plugins/Zeitgeist/images/ico_delete.png' border="0"/>
|
||||
{{ 'General_Delete'|translate }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if userLogin != 'anonymous' %}
|
||||
<br/>
|
||||
<a onclick='' id='linkAddReport'>› {{ 'ScheduledReports_CreateAndScheduleReport'|translate }}</a>
|
||||
<br/>
|
||||
<br/>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
62
www/analytics/plugins/ScheduledReports/templates/index.twig
Normal file
62
www/analytics/plugins/ScheduledReports/templates/index.twig
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{% extends 'dashboard.twig' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "@CoreHome/_siteSelectHeader.twig" %}
|
||||
|
||||
<div class="top_controls">
|
||||
{% include "@CoreHome/_periodSelect.twig" %}
|
||||
</div>
|
||||
|
||||
<div class="centerLargeDiv">
|
||||
<h2 piwik-enriched-headline
|
||||
help-url="http://piwik.org/docs/email-reports/">{{ 'ScheduledReports_ManageEmailReports'|translate }}</h2>
|
||||
<span id="reportSentSuccess"></span>
|
||||
<span id="reportUpdatedSuccess"></span>
|
||||
|
||||
<div class="entityContainer">
|
||||
{% import 'ajaxMacros.twig' as ajax %}
|
||||
{{ ajax.errorDiv() }}
|
||||
{{ ajax.loadingDiv() }}
|
||||
{% include "@ScheduledReports/_listReports.twig" %}
|
||||
{% include "@ScheduledReports/_addReport.twig" %}
|
||||
<a id='bottom'></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui-confirm" id="confirm">
|
||||
<h2>{{ 'ScheduledReports_AreYouSureDeleteReport'|translate }}</h2>
|
||||
<input role="yes" type="button" value="{{ 'General_Yes'|translate }}"/>
|
||||
<input role="no" type="button" value="{{ 'General_No'|translate }}"/>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ReportPlugin = {};
|
||||
ReportPlugin.defaultPeriod = '{{ defaultPeriod }}';
|
||||
ReportPlugin.defaultHour = '{{ defaultHour }}';
|
||||
ReportPlugin.defaultReportType = '{{ defaultReportType }}';
|
||||
ReportPlugin.defaultReportFormat = '{{ defaultReportFormat }}';
|
||||
ReportPlugin.reportList = {{ reportsJSON | raw }};
|
||||
ReportPlugin.createReportString = "{{ 'ScheduledReports_CreateReport'|translate }}";
|
||||
ReportPlugin.updateReportString = "{{ 'ScheduledReports_UpdateReport'|translate }}";
|
||||
$(function () {
|
||||
initManagePdf();
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
.reportCategory {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.entityAddContainer {
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.entityAddContainer > .entityCancel:first-child {
|
||||
position: absolute;
|
||||
right:0;
|
||||
bottom:100%;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<tr class='{{ reportType }}'>
|
||||
<td style='width:240px;' class="first">{{ 'ScheduledReports_SendReportTo'|translate }}
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="report_email_me"/>
|
||||
<label for="report_email_me">{{ 'ScheduledReports_SentToMe'|translate }} (<em>{{ currentUserEmail }}</em>) </label>
|
||||
<br/><br/>
|
||||
{{ 'ScheduledReports_AlsoSendReportToTheseEmails'|translate }}<br/>
|
||||
<textarea cols="30" rows="3" id="report_additional_emails" class="inp"></textarea>
|
||||
<script>
|
||||
function updateEvolutionGraphParameterVisibility() {
|
||||
var evolutionGraphParameterInput = $('.report_evolution_graph');
|
||||
var nonApplicableDisplayFormats = ['1', '4'];
|
||||
$.inArray($('#display_format').find('option:selected').val(), nonApplicableDisplayFormats) != -1 ?
|
||||
evolutionGraphParameterInput.hide() : evolutionGraphParameterInput.show();
|
||||
}
|
||||
|
||||
$(function () {
|
||||
|
||||
resetReportParametersFunctions ['{{ reportType }}'] =
|
||||
function () {
|
||||
|
||||
var reportParameters = {
|
||||
'displayFormat': '{{ defaultDisplayFormat }}',
|
||||
'emailMe': {{ defaultEmailMe }},
|
||||
'evolutionGraph': {{ defaultEvolutionGraph }},
|
||||
'additionalEmails': null
|
||||
};
|
||||
updateReportParametersFunctions['{{ reportType }}'](reportParameters);
|
||||
};
|
||||
|
||||
updateReportParametersFunctions['{{ reportType }}'] =
|
||||
function (reportParameters) {
|
||||
|
||||
if (reportParameters == null) return;
|
||||
|
||||
$('#display_format').find('option[value=' + reportParameters.displayFormat + ']').prop('selected', 'selected');
|
||||
updateEvolutionGraphParameterVisibility();
|
||||
|
||||
if (reportParameters.emailMe === true)
|
||||
$('#report_email_me').prop('checked', 'checked');
|
||||
else
|
||||
$('#report_email_me').removeProp('checked');
|
||||
|
||||
if (reportParameters.evolutionGraph === true)
|
||||
$('#report_evolution_graph').prop('checked', 'checked');
|
||||
else
|
||||
$('#report_evolution_graph').removeProp('checked');
|
||||
|
||||
if (reportParameters.additionalEmails != null)
|
||||
$('#report_additional_emails').text(reportParameters.additionalEmails.join('\n'));
|
||||
else
|
||||
$('#report_additional_emails').html('');
|
||||
|
||||
$(document).trigger('ScheduledReport.edit', {});
|
||||
};
|
||||
|
||||
getReportParametersFunctions['{{ reportType }}'] =
|
||||
function () {
|
||||
|
||||
var parameters = Object();
|
||||
|
||||
parameters.displayFormat = $('#display_format').find('option:selected').val();
|
||||
parameters.emailMe = $('#report_email_me').prop('checked');
|
||||
parameters.evolutionGraph = $('#report_evolution_graph').prop('checked');
|
||||
|
||||
var additionalEmails = $('#report_additional_emails').val();
|
||||
parameters.additionalEmails =
|
||||
additionalEmails != '' ? additionalEmails.split('\n') : [];
|
||||
|
||||
return parameters;
|
||||
};
|
||||
|
||||
$('#display_format').change(updateEvolutionGraphParameterVisibility);
|
||||
});
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
Loading…
Add table
Add a link
Reference in a new issue