1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace SilverStripe\VersionedAdmin\Controllers; |
4
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
6
|
|
|
use SilverStripe\Admin\LeftAndMain; |
7
|
|
|
use SilverStripe\Admin\LeftAndMainFormRequestHandler; |
8
|
|
|
use SilverStripe\Control\HTTPRequest; |
9
|
|
|
use SilverStripe\Control\HTTPResponse; |
10
|
|
|
use SilverStripe\Core\Injector\Injector; |
11
|
|
|
use SilverStripe\Forms\FormFactory; |
12
|
|
|
use SilverStripe\Versioned\Versioned; |
13
|
|
|
use SilverStripe\VersionedAdmin\Forms\DataObjectVersionFormFactory; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* The HistoryViewerController provides AJAX endpoints for React to enable functionality, such as retrieving the form |
17
|
|
|
* schema. |
18
|
|
|
*/ |
19
|
|
|
class HistoryViewerController extends LeftAndMain |
|
|
|
|
20
|
|
|
|
21
|
|
|
private static $url_segment = 'historyviewer'; |
|
|
|
|
22
|
|
|
|
23
|
|
|
private static $url_rule = '/$Action'; |
24
|
|
|
|
25
|
|
|
private static $url_priority = 10; |
26
|
|
|
|
27
|
|
|
private static $required_permission_codes = 'CMS_ACCESS_CMSMain'; |
28
|
|
|
|
29
|
|
|
private static $allowed_actions = [ |
30
|
|
|
'versionForm', |
31
|
|
|
'schema', |
32
|
|
|
]; |
33
|
|
|
|
34
|
|
|
public function getClientConfig() |
35
|
|
|
{ |
36
|
|
|
$clientConfig = parent::getClientConfig(); |
37
|
|
|
|
38
|
|
|
$clientConfig['form']['versionForm'] = [ |
39
|
|
|
'schemaUrl' => $this->owner->Link('schema/versionForm') |
40
|
|
|
]; |
41
|
|
|
|
42
|
|
|
return $clientConfig; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Gets a JSON schema representing the current version detail form. |
47
|
|
|
* |
48
|
|
|
* WARNING: Experimental API. |
49
|
|
|
* |
50
|
|
|
* @param HTTPRequest $request |
51
|
|
|
* @return HTTPResponse |
52
|
|
|
*/ |
53
|
|
|
public function schema($request) |
54
|
|
|
{ |
55
|
|
|
$formName = $request->param('FormName'); |
56
|
|
|
if ($formName !== 'versionForm') { |
57
|
|
|
return parent::schema($request); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
// Get schema for history form |
61
|
|
|
// @todo Eventually all form scaffolding will be based on context rather than record ID |
62
|
|
|
// See https://github.com/silverstripe/silverstripe-framework/issues/6362 |
63
|
|
|
$form = $this->getVersionForm([ |
64
|
|
|
'RecordClass' => $request->getVar('RecordClass'), |
65
|
|
|
'RecordID' => $request->getVar('RecordID'), |
66
|
|
|
'RecordVersion' => $request->getVar('RecordVersion'), |
67
|
|
|
]); |
68
|
|
|
|
69
|
|
|
// Respond with this schema |
70
|
|
|
$response = $this->getResponse(); |
71
|
|
|
$response->addHeader('Content-Type', 'application/json'); |
72
|
|
|
$schemaID = $this->getRequest()->getURL(); |
73
|
|
|
return $this->getSchemaResponse($schemaID, $form); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
public function getVersionForm(array $context) |
77
|
|
|
{ |
78
|
|
|
// Check context |
79
|
|
|
if (!isset($context['RecordClass'], $context['RecordID'], $context['RecordVersion'])) { |
80
|
|
|
throw new InvalidArgumentException('Missing RecordID / RecordVersion / RecordClass for this form'); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
$recordClass = $context['RecordClass']; |
84
|
|
|
$recordId = $context['RecordID']; |
85
|
|
|
$recordVersion = $context['RecordVersion']; |
86
|
|
|
|
87
|
|
|
if (!$recordClass || !$recordId || !$recordVersion) { |
88
|
|
|
$this->jsonError(404); |
89
|
|
|
return null; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
// Load record and perform a canView check |
93
|
|
|
$record = Versioned::get_version($recordClass, $recordId, $recordVersion); |
94
|
|
|
if (!$record) { |
95
|
|
|
$this->jsonError(404); |
96
|
|
|
return null; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
if (!$record->canView()) { |
100
|
|
|
$this->jsonError(403, _t( |
101
|
|
|
__CLASS__.'.ErrorItemViewPermissionDenied', |
102
|
|
|
"You don't have the necessary permissions to view {ObjectTitle}", |
103
|
|
|
['ObjectTitle' => $record->i18n_singular_name()] |
104
|
|
|
)); |
105
|
|
|
return null; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$effectiveContext = array_merge($context, ['Record' => $record]); |
109
|
|
|
/** @var FormFactory $scaffolder */ |
110
|
|
|
$scaffolder = Injector::inst()->get(DataObjectVersionFormFactory::class); |
111
|
|
|
$form = $scaffolder->getForm($this, 'versionForm', $effectiveContext); |
112
|
|
|
|
113
|
|
|
// Set form handler with class name, ID and VersionID |
114
|
|
|
$form->setRequestHandler( |
115
|
|
|
LeftAndMainFormRequestHandler::create($form, [$recordClass, $recordId, $recordVersion]) |
116
|
|
|
); |
117
|
|
|
|
118
|
|
|
return $form; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
public function versionForm(HTTPRequest $request = null) |
122
|
|
|
{ |
123
|
|
|
if (!$request) { |
124
|
|
|
$this->jsonError(400); |
125
|
|
|
return null; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$recordClass = $request->getVar('RecordClass'); |
129
|
|
|
$recordId = $request->getVar('RecordID'); |
130
|
|
|
$recordVersion = $request->getVar('RecordVersion'); |
131
|
|
|
if (!$recordClass || !$recordId || !$recordVersion) { |
132
|
|
|
$this->jsonError(400); |
133
|
|
|
return null; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
return $this->getVersionForm([ |
137
|
|
|
'RecordClass' => $recordClass, |
138
|
|
|
'RecordID' => $recordId, |
139
|
|
|
'RecordVersion' => $recordVersion, |
140
|
|
|
]); |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.