Skip to content

Commit d6e9ea2

Browse files
committed
Initial import
1 parent 4b5f0d3 commit d6e9ea2

127 files changed

Lines changed: 16089 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LICENSE

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Icinga Reporting
2+
3+
Icinga Reporting is the central component for reporting related functionality in the monitoring web frontend and
4+
framework Icinga Web 2. The engine allows you to create reports over a specified time period for ad-hoc and scheduled
5+
generation of reports. Other modules use the provided functionality in order to provide concrete reports.
6+
7+
## Documentation
8+
9+
* [Installation](doc/02-Installation.md)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
// Icinga Reporting | (c) 2018 Icinga GmbH | GPLv2
3+
4+
namespace Icinga\Module\Reporting\Clicommands;
5+
6+
use Icinga\Module\Reporting\Cli\Command;
7+
use Icinga\Module\Reporting\Scheduler;
8+
9+
class ScheduleCommand extends Command
10+
{
11+
/**
12+
* Run all configured reports based on their schedule
13+
*
14+
* USAGE:
15+
*
16+
* icingacli reporting schedule run
17+
*/
18+
public function runAction()
19+
{
20+
$scheduler = new Scheduler($this->getDb());
21+
22+
$scheduler->run();
23+
}
24+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
// Icinga Reporting | (c) 2018 Icinga GmbH | GPLv2
3+
4+
namespace Icinga\Module\Reporting\Controllers;
5+
6+
use Icinga\Application\Config;
7+
use Icinga\Module\Reporting\Forms\SelectBackendForm;
8+
use Icinga\Web\Controller;
9+
10+
class ConfigController extends Controller
11+
{
12+
public function init()
13+
{
14+
$this->assertPermission('config/modules');
15+
16+
parent::init();
17+
}
18+
19+
public function backendAction()
20+
{
21+
$form = (new SelectBackendForm())
22+
->setIniConfig(Config::module('reporting'));
23+
24+
$form->handleRequest();
25+
26+
$this->view->tabs = $this->Module()->getConfigTabs()->activate('backend');
27+
$this->view->form = $form;
28+
}
29+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Icinga\Module\Reporting\Controllers;
4+
5+
use GuzzleHttp\Psr7\ServerRequest;
6+
use Icinga\Module\Reporting\Hook\ReportHook;
7+
use Icinga\Module\Reporting\Web\Forms\ReportForm;
8+
use Icinga\Module\Reporting\Web\Controller;
9+
use Icinga\Web\Hook;
10+
use Icinga\Web\Url;
11+
use ipl\Html\Html;
12+
13+
class PlugController extends Controller
14+
{
15+
public function indexAction()
16+
{
17+
$moduleToShow = strtolower($this->params->get('module', 'reporting'));
18+
19+
$reportsByModule = [];
20+
21+
foreach (ReportHook::getReports() as $class => $report) {
22+
$moduleName = $report->getModuleName();
23+
24+
if (! isset($reportsByModule[$moduleName])) {
25+
$reportsByModule[$moduleName] = [];
26+
}
27+
28+
$reportsByModule[$moduleName][$class] = $report;
29+
}
30+
31+
$editor = Html::tag('div', ['class' => 'editor']);
32+
33+
$nav = [];
34+
35+
$cards = [];
36+
37+
foreach ($reportsByModule as $moduleName => $reports) {
38+
$link = Html::tag('a', ['href' => Url::fromRequest(['module' => $moduleName])], $moduleName);
39+
40+
$nav[] = $link;
41+
42+
if ($moduleName !== $moduleToShow) {
43+
continue;
44+
}
45+
46+
$link->getAttributes()->add('class', 'active');
47+
48+
foreach ($reports as $report) {
49+
$cards[] = Html::tag(
50+
'div',
51+
['class' => 'card'],
52+
[
53+
Html::tag('div', ['class' => 'card-top'], $report->getPreview()),
54+
Html::tag(
55+
'div',
56+
['class' => 'card-content'],
57+
Html::tag('h5', ['class' => 'card-title'], $report->getName()),
58+
Html::tag('p', ['class' => 'card-text'], $report->getDescription())
59+
)
60+
]
61+
);
62+
}
63+
}
64+
65+
$editor->add(Html::tag('div', ['class' => 'editor-nav'], $nav));
66+
$editor->add(Html::tag('div', ['class' => 'editor-content'], $cards));
67+
68+
$this->addContent($editor);
69+
70+
$this->addContent(Html::tag('a', ['href' => 'plug', 'class' => 'modal-toggle', 'data-base-target' => 'modal-container'], 'Modal'));
71+
}
72+
}
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
<?php
2+
// Icinga Reporting | (c) 2018 Icinga GmbH | GPLv2
3+
4+
namespace Icinga\Module\Reporting\Controllers;
5+
6+
use GuzzleHttp\Psr7\ServerRequest;
7+
use Icinga\Application\Hook;
8+
use Icinga\Module\Reporting\Database;
9+
use Icinga\Module\Reporting\Report;
10+
use Icinga\Module\Reporting\Web\Controller;
11+
use Icinga\Module\Reporting\Web\Forms\ReportForm;
12+
use Icinga\Module\Reporting\Web\Forms\ScheduleForm;
13+
use Icinga\Module\Reporting\Web\Forms\SendForm;
14+
use Icinga\Web\StyleSheet;
15+
use ipl\Html\Html;
16+
use ipl\Html\HtmlString;
17+
use reportingipl\Web\Url;
18+
use reportingipl\Web\Widget\ActionBar;
19+
use reportingipl\Web\Widget\DropdownLink;
20+
21+
class ReportController extends Controller
22+
{
23+
use Database;
24+
25+
/** @var Report */
26+
protected $report;
27+
28+
public function init()
29+
{
30+
$this->report = Report::fromDb($this->params->getRequired('id'));
31+
}
32+
33+
public function indexAction()
34+
{
35+
$this->setTitle($this->report->getName());
36+
37+
$this->addControl($this->assembleActions());
38+
39+
$this->addContent($this->report->toHtml());
40+
}
41+
42+
public function editAction()
43+
{
44+
$this->setTitle('Edit Report');
45+
46+
$values = [
47+
'name' => $this->report->getName(),
48+
// TODO(el): Must cast to string here because ipl/html does not support integer return values for attribute callbacks
49+
'timeframe' => (string) $this->report->getTimeframe()->getId(),
50+
];
51+
52+
$reportlet = $this->report->getReportlets()[0];
53+
54+
$values['reportlet'] = $reportlet->getClass();
55+
56+
foreach ($reportlet->getConfig() as $name => $value) {
57+
$values[$name] = $value;
58+
}
59+
60+
$form = new ReportForm();
61+
$form->setId($this->report->getId());
62+
$form->populate($values);
63+
$form->handleRequest(ServerRequest::fromGlobals());
64+
65+
$this->redirectForm($form, 'reporting/reports');
66+
67+
$this->addContent($form);
68+
}
69+
70+
public function sendAction()
71+
{
72+
$this->setTitle('Send Report');
73+
74+
$form = new SendForm();
75+
$form
76+
->setReport($this->report)
77+
->handleRequest(ServerRequest::fromGlobals());
78+
79+
$this->redirectForm($form, "reporting/report?id={$this->report->getId()}");
80+
81+
$this->addContent($form);
82+
}
83+
84+
public function scheduleAction()
85+
{
86+
$this->setTitle('Schedule');
87+
88+
$form = new ScheduleForm();
89+
$form
90+
->setReport($this->report)
91+
->handleRequest(ServerRequest::fromGlobals());
92+
93+
$this->redirectForm($form, "reporting/report?id={$this->report->getId()}");
94+
95+
$this->addContent($form);
96+
}
97+
98+
public function downloadAction()
99+
{
100+
$type = $this->params->getRequired('type');
101+
102+
$name = sprintf(
103+
'%s (%s) %s',
104+
$this->report->getName(),
105+
$this->report->getTimeframe()->getName(),
106+
date('Y-m-d H:i')
107+
);
108+
109+
switch ($type) {
110+
case 'pdf':
111+
$pdfexport = null;
112+
113+
if (Hook::has('Pdfexport')) {
114+
$pdfexport = Hook::first('Pdfexport');
115+
116+
if (! $pdfexport->isSupported()) {
117+
throw new \Exception("Can't export");
118+
}
119+
}
120+
121+
if (! $pdfexport) {
122+
throw new \Exception("Can't export");
123+
}
124+
125+
$html = Html::tag(
126+
'html',
127+
null,
128+
[
129+
Html::tag(
130+
'head',
131+
null,
132+
Html::tag(
133+
'style',
134+
null,
135+
new HtmlString(StyleSheet::forPdf())
136+
)
137+
),
138+
Html::tag(
139+
'body',
140+
null,
141+
Html::tag(
142+
'div',
143+
['class' => 'icinga-module module-reporting'],
144+
new HtmlString($this->report->toHtml())
145+
)
146+
)
147+
]
148+
);
149+
150+
/** @var Hook\PdfexportHook */
151+
$pdfexport->streamPdfFromHtml((string) $html, $name);
152+
exit;
153+
case 'csv':
154+
$response = $this->getResponse();
155+
$response
156+
->setHeader('Content-Type', 'text/csv')
157+
->setHeader('Cache-Control', 'no-store')
158+
->setHeader(
159+
'Content-Disposition',
160+
'attachment; filename=' . $name . '.csv'
161+
)
162+
->appendBody($this->report->toCsv())
163+
->sendResponse();
164+
exit;
165+
case 'json':
166+
$response = $this->getResponse();
167+
$response
168+
->setHeader('Content-Type', 'application/json')
169+
->setHeader('Cache-Control', 'no-store')
170+
->setHeader(
171+
'Content-Disposition',
172+
'inline; filename=' . $name . '.json'
173+
)
174+
->appendBody($this->report->toJson())
175+
->sendResponse();
176+
exit;
177+
}
178+
}
179+
180+
protected function assembleActions()
181+
{
182+
$reportId = $this->report->getId();
183+
184+
$download = (new DropdownLink('Download'))
185+
->addLink('PDF', Url::fromPath('reporting/report/download?type=pdf', ['id' => $reportId]));
186+
187+
if ($this->report->providesData()) {
188+
$download->addLink('CSV', Url::fromPath('reporting/report/download?type=csv', ['id' => $reportId]));
189+
$download->addLink('JSON', Url::fromPath('reporting/report/download?type=json', ['id' => $reportId]));
190+
}
191+
192+
$actions = new ActionBar();
193+
194+
$actions
195+
->addLink('Modify', Url::fromPath('reporting/report/edit', ['id' => $reportId]), 'edit')
196+
->addLink('Schedule', Url::fromPath('reporting/report/schedule', ['id' => $reportId]), 'calendar-empty')
197+
->add($download)
198+
->addLink('Send', Url::fromPath('reporting/report/send', ['id' => $reportId]), 'forward');
199+
200+
return $actions;
201+
}
202+
}

0 commit comments

Comments
 (0)