Completed
Push — master ( 30e1bf...007fe5 )
by Marcus
16s queued 11s
created

code/admin/WorkflowDefinitionExporter.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Allows workflow definitions to be exported from one SilverStripe install, ready for import into another.
4
 * 
5
 * YAML is used for export as it's native to SilverStripe's config system and we're using {@link WorkflowTemplate}
6
 * for some of the import-specific heavy lifting, which is already heavily predicated on YAML.
7
 * 
8
 * @todo
9
 *	- If workflow-def is created badly, the "update template definition" logic, sometimes doesn't work
10
 * 
11
 * @author  [email protected]
12
 * @license BSD License (http://silverstripe.org/bsd-license/)
13
 * @package advancedworkflow
14
 */
15
class WorkflowDefinitionExporter {
16
	
17
	/**
18
	 * The base filename of the file to the exported
19
	 * 
20
	 * @var string
21
	 */
22
	public static $export_filename_prefix = 'workflow-definition-export';
23
	/**
24
	 *
25
	 * @var \Member
26
	 */
27
	protected $member;
28
	/**
29
	 * 
30
	 * @var \WorkflowDefinition
31
	 */
32
	protected $workflowDefinition;
33
	
34
	/**
35
	 * 
36
	 * @param number $definitionID
37
	 * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
38
	 */
39
	public function __construct($definitionID) {
40
		$this->setMember(Member::currentUser());
41
		$this->workflowDefinition = DataObject::get_by_id('WorkflowDefinition', $definitionID);		
42
	}
43
	
44
	/**
45
	 * 
46
	 * @param \Member $member
47
	 */
48
	public function setMember($member) {
49
		$this->member = $member;
50
	}
51
	
52
	/**
53
	 * @return \WorkflowDefinition
54
	 */
55
	public function getDefinition() {
56
		return $this->workflowDefinition;
57
	}
58
	
59
	/**
60
	 * Runs the export 
61
	 * 
62
	 * @return string $template
63
	 */
64
	public function export() {
65
		// Disable any access to use of WorkflowExport if user has no SecurityAdmin access
66
		if(!Permission::check('CMS_ACCESS_SecurityAdmin')) {
67
			throw Exception(_t('ErrorPage.403'), 403);
68
		}		
69
		$def = $this->getDefinition();
70
		$templateData = new ArrayData(array(
71
			'ExportMetaData' => $this->ExportMetaData(),
72
			'ExportActions' => $def->Actions(),
73
			'ExportUsers' => $def->Users(),
74
			'ExportGroups' => $def->Groups() 
75
		));
76
		return $this->format($templateData);
77
	}
78
	
79
	/**
80
	 * Format the exported data as YAML.
81
	 * 
82
	 * @param \ArrayData $templateData
83
	 * @return void
84
	 */
85
	public function format($templateData) {
86
		$viewer = SSViewer::execute_template('WorkflowDefinitionExport', $templateData);
87
		// Temporary until we find the source of the replacement in SSViewer
88
		$processed = str_replace('&amp;', '&', $viewer);
89
		// Clean-up newline "gaps" that SSViewer leaves behind from the placement of template control structures
90
		return preg_replace("#^\R+|^[\t\s]*\R+#m", '', $processed);
91
	}
92
	
93
	/**
94
	 * Returns the size of the current export in bytes.
95
	 * Used for pushing data to the browser to prompt for download
96
	 * 
97
	 * @param string $str
98
	 * @return number $bytes
99
	 */
100
	public function getExportSize($str) {
101
		return mb_strlen($str, 'UTF-8');
102
	}
103
104
	/**
105
	 * Generate template vars for metadata
106
	 * 
107
	 * @return ArrayData
108
	 */
109
	public function ExportMetaData() {
110
		$def = $this->getDefinition();
111
		return new ArrayData(array(
112
			'ExportHost' => preg_replace("#http(s)?://#", '', Director::protocolAndHost()),
113
			'ExportDate' => date('d/m/Y H-i-s'),
114
			'ExportUser' => $this->member->FirstName.' '.$this->member->Surname,
115
			'ExportVersionFramework' => $this->ssVersion(),
116
			'ExportWorkflowDefName' => $this->processTitle($def->Title),
117
			'ExportRemindDays' => $def->RemindDays,
118
			'ExportSort' => $def->Sort
119
		));
120
	}
121
	
122
	/*
123
	 * Try different ways of obtaining the current SilverStripe version for YAML output.
124
	 * 
125
	 * @return string
126
	 */
127
	private function ssVersion() {
128
		// Remove colons so they don't screw with YAML parsing
129
		$versionSapphire = str_replace(':', '', singleton('SapphireInfo')->Version());
130
		$versionLeftMain = str_replace(':', '', singleton('LeftAndMain')->CMSVersion());
131
		if($versionSapphire != _t('LeftAndMain.VersionUnknown')) {
132
			return $versionSapphire;
133
		}
134
		return $versionLeftMain;
135
	}
136
	
137
	private function processTitle($title) {
138
		// If an import is exported and re-imported, the new export date is appended to Title, making for a very long title
139
		return preg_replace("#\s[\d]+\/[\d]+\/[\d]+\s[\d]+-[\d]+-[\d]+(\s[\d]+)?#", '', $title);	
140
	}
141
	
142
	/**
143
	 * Prompt the client for file download.
144
	 * We're "overriding" SS_HTTPRequest::send_file() for more robust cross-browser support
145
	 * 
146
	 * @param array $filedata
147
	 * @return \SS_HTTPResponse $response
148
	 */
149
	public function sendFile($filedata) {
150
		$response = new SS_HTTPResponse($filedata['body']);
151
		if(preg_match("#MSIE\s(6|7|8)?\.0#",$_SERVER['HTTP_USER_AGENT'])) {
152
			// IE headers
153
			$response->addHeader("Cache-Control","public");
154
			$response->addHeader("Content-Disposition","attachment; filename=\"".basename($filedata['name'])."\"");
155
			$response->addHeader("Content-Type","application/force-download");
156
			$response->addHeader("Content-Type","application/octet-stream");
157
			$response->addHeader("Content-Type","application/download");
158
			$response->addHeader("Content-Type",$filedata['mime']);
159
			$response->addHeader("Content-Description","File Transfer");
160
			$response->addHeader("Content-Length",$filedata['size']);	
161
		}
162
		else {
163
			// Everyone else
164
			$response->addHeader("Content-Type", $filedata['mime']."; name=\"".addslashes($filedata['name'])."\"");
165
			$response->addHeader("Content-disposition", "attachment; filename=".addslashes($filedata['name']));
166
			$response->addHeader("Content-Length",$filedata['size']);
167
		}
168
		return $response;
169
	}
170
	
171
}
172