├── .gitignore ├── README.md ├── _build ├── build.config.php ├── build.model.php ├── build.transport.php ├── data │ ├── permissions │ │ └── fileattach.policy.php │ ├── transport.chunks.php │ ├── transport.events.php │ ├── transport.menu.php │ ├── transport.plugins.php │ ├── transport.policies.php │ ├── transport.policytemplates.php │ ├── transport.settings.php │ └── transport.snippets.php ├── includes │ └── functions.php ├── properties │ ├── properties.fileattach.php │ └── properties.filelink.php ├── resolvers │ ├── resolve.chunks.php │ ├── resolve.policy.php │ ├── resolve.setup.php │ └── resolve.tables.php └── setup.options.php ├── assets └── components │ └── fileattach │ ├── connector.php │ └── js │ └── mgr │ ├── fileattach.js │ ├── filestab.js │ └── widgets │ ├── home.panel.js │ └── items.grid.js └── core └── components └── fileattach ├── controllers └── list.class.php ├── docs ├── changelog.txt ├── license.txt └── readme.txt ├── elements ├── chunks │ └── chunk.item.tpl ├── plugins │ └── plugin.filestab.php ├── snippets │ ├── snippet.fileattach.php │ └── snippet.filelink.php └── templates │ └── home.tpl ├── lexicon ├── en │ ├── default.inc.php │ ├── permissions.inc.php │ ├── properties.inc.php │ ├── setting.inc.php │ └── source.inc.php └── ru │ ├── default.inc.php │ ├── permissions.inc.php │ ├── properties.inc.php │ ├── setting.inc.php │ └── source.inc.php ├── model ├── fileattach │ ├── fileattach.class.php │ ├── fileattachmediasource.class.php │ ├── fileitem.class.php │ ├── metadata.mysql.php │ ├── metadata.sqlsrv.php │ ├── mysql │ │ ├── fileattachmediasource.class.php │ │ ├── fileattachmediasource.map.inc.php │ │ ├── fileitem.class.php │ │ └── fileitem.map.inc.php │ └── sqlsrv │ │ ├── fileattachmediasource.class.php │ │ ├── fileattachmediasource.map.inc.php │ │ ├── fileitem.class.php │ │ └── fileitem.map.inc.php └── schema │ ├── fileattach.mysql.schema.xml │ └── fileattach.sqlsrv.schema.xml └── processors ├── mgr ├── access.class.php ├── create.class.php ├── get.class.php ├── getlist.class.php ├── hash.class.php ├── rank.class.php ├── remove.class.php ├── reset.class.php ├── searchres.class.php ├── update.class.php └── upload.class.php └── web ├── download.class.php ├── getlist.class.php └── remove.class.php /.gitignore: -------------------------------------------------------------------------------- 1 | config.core.php 2 | .idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## FileAttach 2 | 3 | FileAttach is a tool to create file collections. 4 | Package provides UI for MODx Manager to upload files to Resources, 5 | manage file list, view download statistics, snippet for front-end listing. 6 | Allows to count downloads, keep files privately (without direct url), 7 | calculate SHA1 hash for uploaded files. Works with MediaSource. 8 | Provides MediaSource to view tree with Resources and files attached to them. 9 | 10 | ## How to Export 11 | 12 | First, clone this repository somewhere on your development machine: 13 | 14 | `git clone http://github.com/13hakta/FileAttach.git ./` 15 | 16 | Then, create the target directory where you want to create the file. 17 | 18 | Then, navigate to the directory FileAttach is now in, and do this: 19 | 20 | `git archive HEAD | (cd /path/where/I/want/my/new/repo/ && tar -xvf -)` 21 | 22 | (Windows users can just do git archive HEAD and extract the tar file to wherever 23 | they want.) 24 | 25 | Then you can git init or whatever in that directory, and your files will be located 26 | there! 27 | 28 | ## Configuration 29 | 30 | Now, you'll want to change references to FileAttach in the files in your 31 | new copied-from-FileAttach repo to whatever name of your new Extra will be. Once 32 | you've done that, you can create some System Settings: 33 | 34 | - 'mynamespace.core_path' - Point to /path/to/my/extra/core/components/extra/ 35 | - 'mynamespace.assets_url' - /path/to/my/extra/assets/components/extra/ 36 | 37 | Then clear the cache. This will tell the Extra to look for the files located 38 | in these directories, allowing you to develop outside of the MODx webroot! 39 | 40 | ## Information 41 | 42 | Note that if you git archive from this repository, you may not need all of its 43 | functionality. This Extra contains files and the setup to do the following: 44 | 45 | - Integrates a custom table of "FileItem" 46 | - A snippet listing Items sorted by name and templated with a chunk 47 | - A snippet showing link to get inline content 48 | - A custom manager page to manage FileItem on 49 | 50 | If you do not require all of this functionality, simply remove it and change the 51 | appropriate code. 52 | 53 | Also, you'll want to change all the references of 'FileAttach' to whatever the 54 | name of your component is. 55 | 56 | ## Copyright Information 57 | 58 | FileAttach is distributed as GPL (as MODx Revolution is), but the copyright owner 59 | (Vitaly Chekryzhev) grants all users of FileAttach the ability to modify, distribute 60 | and use FileAttach in MODx development as they see fit, as long as attribution 61 | is given somewhere in the distributed source of all derivative works. -------------------------------------------------------------------------------- /_build/build.config.php: -------------------------------------------------------------------------------- 1 | $root, 11 | 'build' => $root . '_build/', 12 | 'source_core' => $root . 'core/components/' . PKG_NAME_LOWER, 13 | 'model' => $root . 'core/components/' . PKG_NAME_LOWER . '/model/', 14 | 'schema' => $root . 'core/components/' . PKG_NAME_LOWER . '/model/schema/', 15 | 'xml' => $root . 'core/components/' . PKG_NAME_LOWER . '/model/schema/' . PKG_NAME_LOWER . '.mysql.schema.xml', 16 | 'xml2' => $root . 'core/components/' . PKG_NAME_LOWER . '/model/schema/' . PKG_NAME_LOWER . '.sqlsrv.schema.xml', 17 | ); 18 | unset($root); 19 | 20 | require MODX_CORE_PATH . 'model/modx/modx.class.php'; 21 | require $sources['build'] . '/includes/functions.php'; 22 | 23 | $modx = new modX(); 24 | $modx->initialize('mgr'); 25 | $modx->getService('error', 'error.modError'); 26 | $modx->setLogLevel(modX::LOG_LEVEL_INFO); 27 | $modx->setLogTarget('ECHO'); 28 | $modx->loadClass('transport.modPackageBuilder', '', false, true); 29 | if (!XPDO_CLI_MODE) { 30 | echo '
';
31 | }
32 | 
33 | /** @var xPDOManager $manager */
34 | $manager = $modx->getManager();
35 | /** @var xPDOGenerator $generator */
36 | $generator = $manager->getGenerator();
37 | 
38 | // Remove old model
39 | rrmdir($sources['model'] . PKG_NAME_LOWER . '/mysql');
40 | rrmdir($sources['model'] . PKG_NAME_LOWER . '/sqlsrv');
41 | 
42 | // Generate a new one
43 | $generator->parseSchema($sources['xml'], $sources['model']);
44 | $generator->parseSchema($sources['xml2'], $sources['model']);
45 | 
46 | $modx->log(modX::LOG_LEVEL_INFO, 'Model generated.');
47 | if (!XPDO_CLI_MODE) {
48 | 	echo '
'; 49 | } -------------------------------------------------------------------------------- /_build/build.transport.php: -------------------------------------------------------------------------------- 1 | $root, 21 | 'build' => $root . '_build/', 22 | 'data' => $root . '_build/data/', 23 | 'resolvers' => $root . '_build/resolvers/', 24 | 'chunks' => $root . 'core/components/' . PKG_NAME_LOWER . '/elements/chunks/', 25 | 'snippets' => $root . 'core/components/' . PKG_NAME_LOWER . '/elements/snippets/', 26 | 'plugins' => $root . 'core/components/' . PKG_NAME_LOWER . '/elements/plugins/', 27 | 'lexicon' => $root . 'core/components/' . PKG_NAME_LOWER . '/lexicon/', 28 | 'docs' => $root . 'core/components/' . PKG_NAME_LOWER . '/docs/', 29 | 'source_assets' => $root . 'assets/components/' . PKG_NAME_LOWER, 30 | 'source_core' => $root . 'core/components/' . PKG_NAME_LOWER, 31 | ); 32 | unset($root); 33 | 34 | require_once MODX_CORE_PATH . 'model/modx/modx.class.php'; 35 | require_once $sources['build'] . '/includes/functions.php'; 36 | 37 | $modx = new modX(); 38 | $modx->initialize('mgr'); 39 | $modx->setLogLevel(modX::LOG_LEVEL_INFO); 40 | $modx->setLogTarget('ECHO'); 41 | $modx->getService('error', 'error.modError'); 42 | $modx->loadClass('transport.modPackageBuilder', '', false, true); 43 | if (!XPDO_CLI_MODE) { 44 | echo '
';
 45 | }
 46 | 
 47 | $builder = new modPackageBuilder($modx);
 48 | $builder->createPackage(PKG_NAME_LOWER, PKG_VERSION, PKG_RELEASE);
 49 | $builder->registerNamespace(PKG_NAME_LOWER, false, true, PKG_NAMESPACE_PATH, PKG_ASSETS_PATH);
 50 | 
 51 | $modx->log(modX::LOG_LEVEL_INFO, 'Created Transport Package and Namespace.');
 52 | 
 53 | /* load system settings */
 54 | if (defined('BUILD_SETTING_UPDATE')) {
 55 | 	$settings = include $sources['data'] . 'transport.settings.php';
 56 | 	if (!is_array($settings)) {
 57 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in settings.');
 58 | 	}
 59 | 	else {
 60 | 		$attributes = array(
 61 | 			xPDOTransport::UNIQUE_KEY => 'key',
 62 | 			xPDOTransport::PRESERVE_KEYS => true,
 63 | 			xPDOTransport::UPDATE_OBJECT => BUILD_SETTING_UPDATE,
 64 | 		);
 65 | 		foreach ($settings as $setting) {
 66 | 			$vehicle = $builder->createVehicle($setting, $attributes);
 67 | 			$builder->putVehicle($vehicle);
 68 | 		}
 69 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($settings) . ' System Settings.');
 70 | 	}
 71 | 	unset($settings, $setting, $attributes);
 72 | }
 73 | 
 74 | /* load plugins events */
 75 | if (defined('BUILD_EVENT_UPDATE')) {
 76 | 	$events = include $sources['data'] . 'transport.events.php';
 77 | 	if (!is_array($events)) {
 78 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in events.');
 79 | 	}
 80 | 	else {
 81 | 		$attributes = array(
 82 | 			xPDOTransport::PRESERVE_KEYS => true,
 83 | 			xPDOTransport::UPDATE_OBJECT => BUILD_EVENT_UPDATE,
 84 | 		);
 85 | 		foreach ($events as $event) {
 86 | 			$vehicle = $builder->createVehicle($event, $attributes);
 87 | 			$builder->putVehicle($vehicle);
 88 | 		}
 89 | 		$modx->log(xPDO::LOG_LEVEL_INFO, 'Packaged in ' . count($events) . ' Plugins events.');
 90 | 	}
 91 | 	unset ($events, $event, $attributes);
 92 | }
 93 | 
 94 | /* package in default access policy */
 95 | if (defined('BUILD_POLICY_UPDATE')) {
 96 | 	$attributes = array(
 97 | 		xPDOTransport::PRESERVE_KEYS => false,
 98 | 		xPDOTransport::UNIQUE_KEY => array('name'),
 99 | 		xPDOTransport::UPDATE_OBJECT => BUILD_POLICY_UPDATE,
100 | 	);
101 | 	$policies = include $sources['data'] . 'transport.policies.php';
102 | 	if (!is_array($policies)) {
103 | 		$modx->log(modX::LOG_LEVEL_FATAL, 'Adding policies failed.');
104 | 	}
105 | 	foreach ($policies as $policy) {
106 | 		$vehicle = $builder->createVehicle($policy, $attributes);
107 | 		$builder->putVehicle($vehicle);
108 | 	}
109 | 	$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($policies) . ' Access Policies.');
110 | 	flush();
111 | 	unset($policies, $policy, $attributes);
112 | }
113 | 
114 | /* package in default access policy templates */
115 | if (defined('BUILD_POLICY_TEMPLATE_UPDATE')) {
116 | 	$templates = include dirname(__FILE__) . '/data/transport.policytemplates.php';
117 | 	$attributes = array(
118 | 		xPDOTransport::PRESERVE_KEYS => false,
119 | 		xPDOTransport::UNIQUE_KEY => array('name'),
120 | 		xPDOTransport::UPDATE_OBJECT => BUILD_POLICY_TEMPLATE_UPDATE,
121 | 		xPDOTransport::RELATED_OBJECTS => true,
122 | 		xPDOTransport::RELATED_OBJECT_ATTRIBUTES => array(
123 | 			'Permissions' => array(
124 | 				xPDOTransport::PRESERVE_KEYS => false,
125 | 				xPDOTransport::UPDATE_OBJECT => BUILD_PERMISSION_UPDATE,
126 | 				xPDOTransport::UNIQUE_KEY => array('template', 'name'),
127 | 			),
128 | 		)
129 | 	);
130 | 	if (is_array($templates)) {
131 | 		foreach ($templates as $template) {
132 | 			$vehicle = $builder->createVehicle($template, $attributes);
133 | 			$builder->putVehicle($vehicle);
134 | 		}
135 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($templates) . ' Access Policy Templates.');
136 | 		flush();
137 | 	}
138 | 	else {
139 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in Access Policy Templates.');
140 | 	}
141 | 	unset ($templates, $template, $attributes);
142 | }
143 | 
144 | /* load menus */
145 | if (defined('BUILD_MENU_UPDATE')) {
146 | 	$menus = include $sources['data'] . 'transport.menu.php';
147 | 
148 | 	$attributes = array(
149 | 		xPDOTransport::PRESERVE_KEYS => true,
150 | 		xPDOTransport::UPDATE_OBJECT => BUILD_MENU_UPDATE,
151 | 		xPDOTransport::UNIQUE_KEY => 'text',
152 | 		xPDOTransport::RELATED_OBJECTS => true
153 | 	);
154 | 
155 | 	if (is_array($menus)) {
156 | 		foreach ($menus as $menu) {
157 | 			$vehicle = $builder->createVehicle($menu, $attributes);
158 | 			$builder->putVehicle($vehicle);
159 | 			/* @var modMenu $menu */
160 | 			$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in menu "' . $menu->get('text') . '".');
161 | 		}
162 | 	}
163 | 	else {
164 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in menu.');
165 | 	}
166 | 	unset($vehicle, $menus, $menu, $attributes);
167 | }
168 | 
169 | 
170 | /* create category */
171 | $modx->log(xPDO::LOG_LEVEL_INFO, 'Created category.');
172 | /* @var modCategory $category */
173 | $category = $modx->newObject('modCategory');
174 | $category->set('category', PKG_NAME);
175 | /* create category vehicle */
176 | $attr = array(
177 | 	xPDOTransport::UNIQUE_KEY => 'category',
178 | 	xPDOTransport::PRESERVE_KEYS => false,
179 | 	xPDOTransport::UPDATE_OBJECT => true,
180 | 	xPDOTransport::RELATED_OBJECTS => true,
181 | );
182 | 
183 | /* add snippets */
184 | if (defined('BUILD_SNIPPET_UPDATE')) {
185 | 	$attr[xPDOTransport::RELATED_OBJECT_ATTRIBUTES]['Snippets'] = array(
186 | 		xPDOTransport::PRESERVE_KEYS => false,
187 | 		xPDOTransport::UPDATE_OBJECT => BUILD_SNIPPET_UPDATE,
188 | 		xPDOTransport::UNIQUE_KEY => 'name',
189 | 	);
190 | 	$snippets = include $sources['data'] . 'transport.snippets.php';
191 | 	if (!is_array($snippets)) {
192 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in snippets.');
193 | 	}
194 | 	else {
195 | 		$category->addMany($snippets);
196 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($snippets) . ' snippets.');
197 | 	}
198 | }
199 | 
200 | /* add chunks */
201 | if (defined('BUILD_CHUNK_UPDATE')) {
202 | 	$attr[xPDOTransport::RELATED_OBJECT_ATTRIBUTES]['Chunks'] = array(
203 | 		xPDOTransport::PRESERVE_KEYS => false,
204 | 		xPDOTransport::UPDATE_OBJECT => BUILD_CHUNK_UPDATE,
205 | 		xPDOTransport::UNIQUE_KEY => 'name',
206 | 	);
207 | 	$chunks = include $sources['data'] . 'transport.chunks.php';
208 | 	if (!is_array($chunks)) {
209 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in chunks.');
210 | 	}
211 | 	else {
212 | 		$category->addMany($chunks);
213 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($chunks) . ' chunks.');
214 | 	}
215 | }
216 | 
217 | /* add plugins */
218 | if (defined('BUILD_PLUGIN_UPDATE')) {
219 | 	$attr[xPDOTransport::RELATED_OBJECT_ATTRIBUTES]['Plugins'] = array(
220 | 		xPDOTransport::PRESERVE_KEYS => false,
221 | 		xPDOTransport::UPDATE_OBJECT => BUILD_PLUGIN_UPDATE,
222 | 		xPDOTransport::UNIQUE_KEY => 'name',
223 | 	);
224 | 	$attr[xPDOTransport::RELATED_OBJECT_ATTRIBUTES]['PluginEvents'] = array(
225 | 		xPDOTransport::PRESERVE_KEYS => true,
226 | 		xPDOTransport::UPDATE_OBJECT => BUILD_EVENT_UPDATE,
227 | 		xPDOTransport::UNIQUE_KEY => array('pluginid', 'event'),
228 | 	);
229 | 	$plugins = include $sources['data'] . 'transport.plugins.php';
230 | 	if (!is_array($plugins)) {
231 | 		$modx->log(modX::LOG_LEVEL_ERROR, 'Could not package in plugins.');
232 | 	}
233 | 	else {
234 | 		$category->addMany($plugins);
235 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Packaged in ' . count($plugins) . ' plugins.');
236 | 	}
237 | }
238 | 
239 | $vehicle = $builder->createVehicle($category, $attr);
240 | 
241 | /* now pack in resolvers */
242 | $vehicle->resolve('file', array(
243 | 	'source' => $sources['source_assets'],
244 | 	'target' => "return MODX_ASSETS_PATH . 'components/';",
245 | ));
246 | $vehicle->resolve('file', array(
247 | 	'source' => $sources['source_core'],
248 | 	'target' => "return MODX_CORE_PATH . 'components/';",
249 | ));
250 | 
251 | foreach ($BUILD_RESOLVERS as $resolver) {
252 | 	if ($vehicle->resolve('php', array('source' => $sources['resolvers'] . 'resolve.' . $resolver . '.php'))) {
253 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Added resolver "' . $resolver . '" to category.');
254 | 	}
255 | 	else {
256 | 		$modx->log(modX::LOG_LEVEL_INFO, 'Could not add resolver "' . $resolver . '" to category.');
257 | 	}
258 | }
259 | 
260 | flush();
261 | $builder->putVehicle($vehicle);
262 | 
263 | /* now pack in the license file, readme and setup options */
264 | $builder->setPackageAttributes(array(
265 | 	'changelog' => file_get_contents($sources['docs'] . 'changelog.txt'),
266 | 	'license' => file_get_contents($sources['docs'] . 'license.txt'),
267 | 	'readme' => file_get_contents($sources['docs'] . 'readme.txt'),
268 | 	'setup-options' => array(
269 | 		'source' => $sources['build'] . 'setup.options.php',
270 | 	),
271 | ));
272 | $modx->log(modX::LOG_LEVEL_INFO, 'Added package attributes and setup options.');
273 | 
274 | /* zip up package */
275 | $modx->log(modX::LOG_LEVEL_INFO, 'Packing up transport package zip...');
276 | $builder->pack();
277 | 
278 | $mtime = microtime();
279 | $mtime = explode(" ", $mtime);
280 | $mtime = $mtime[1] + $mtime[0];
281 | $tend = $mtime;
282 | $totalTime = ($tend - $tstart);
283 | $totalTime = sprintf("%2.4f s", $totalTime);
284 | 
285 | $signature = $builder->getSignature();
286 | if (defined('PKG_AUTO_INSTALL') && PKG_AUTO_INSTALL) {
287 | 	$sig = explode('-', $signature);
288 | 	$versionSignature = explode('.', $sig[1]);
289 | 
290 | 	/* @var modTransportPackage $package */
291 | 	if (!$package = $modx->getObject('transport.modTransportPackage', array('signature' => $signature))) {
292 | 		$package = $modx->newObject('transport.modTransportPackage');
293 | 		$package->set('signature', $signature);
294 | 		$package->fromArray(array(
295 | 			'created' => date('Y-m-d h:i:s'),
296 | 			'updated' => null,
297 | 			'state' => 1,
298 | 			'workspace' => 1,
299 | 			'provider' => 0,
300 | 			'source' => $signature . '.transport.zip',
301 | 			'package_name' => $sig[0],
302 | 			'version_major' => $versionSignature[0],
303 | 			'version_minor' => !empty($versionSignature[1]) ? $versionSignature[1] : 0,
304 | 			'version_patch' => !empty($versionSignature[2]) ? $versionSignature[2] : 0,
305 | 		));
306 | 		if (!empty($sig[2])) {
307 | 			$r = preg_split('/([0-9]+)/', $sig[2], -1, PREG_SPLIT_DELIM_CAPTURE);
308 | 			if (is_array($r) && !empty($r)) {
309 | 				$package->set('release', $r[0]);
310 | 				$package->set('release_index', (isset($r[1]) ? $r[1] : '0'));
311 | 			}
312 | 			else {
313 | 				$package->set('release', $sig[2]);
314 | 			}
315 | 		}
316 | 		$package->save();
317 | 	}
318 | 
319 | 	if ($package->install()) {
320 | 		$modx->runProcessor('system/clearcache');
321 | 	}
322 | }
323 | if (!empty($_GET['download'])) {
324 | 	echo '';
325 | }
326 | 
327 | $modx->log(modX::LOG_LEVEL_INFO, "\n
Execution time: {$totalTime}\n"); 328 | if (!XPDO_CLI_MODE) { 329 | echo '
'; 330 | } 331 | -------------------------------------------------------------------------------- /_build/data/permissions/fileattach.policy.php: -------------------------------------------------------------------------------- 1 | newObject('modAccessPermission',array( 11 | 'name' => 'fileattach.totallist', 12 | 'description' => 'perm.fileattach_all', 13 | 'value' => true, 14 | )); 15 | 16 | $permissions[] = $modx->newObject('modAccessPermission',array( 17 | 'name' => 'fileattach.doclist', 18 | 'description' => 'perm.fileattach_doc', 19 | 'value' => true, 20 | )); 21 | 22 | $permissions[] = $modx->newObject('modAccessPermission',array( 23 | 'name' => 'fileattach.download', 24 | 'description' => 'perm.fileattach_download', 25 | 'value' => true, 26 | )); 27 | 28 | $permissions[] = $modx->newObject('modAccessPermission',array( 29 | 'name' => 'fileattach.list', 30 | 'description' => 'perm.fileattach_list', 31 | 'value' => true, 32 | )); 33 | 34 | $permissions[] = $modx->newObject('modAccessPermission',array( 35 | 'name' => 'fileattach.remove', 36 | 'description' => 'perm.fileattach_remove', 37 | 'value' => true, 38 | )); 39 | 40 | return $permissions; -------------------------------------------------------------------------------- /_build/data/transport.chunks.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'file' => 'item', 8 | 'description' => '', 9 | ), 10 | ); 11 | 12 | // Save chunks for setup options 13 | $BUILD_CHUNKS = array(); 14 | 15 | foreach ($tmp as $k => $v) { 16 | /* @avr modChunk $chunk */ 17 | $chunk = $modx->newObject('modChunk'); 18 | $chunk->fromArray(array( 19 | 'id' => 0, 20 | 'name' => $k, 21 | 'description' => @$v['description'], 22 | 'snippet' => file_get_contents($sources['source_core'] . '/elements/chunks/chunk.' . $v['file'] . '.tpl'), 23 | 'static' => BUILD_CHUNK_STATIC, 24 | 'source' => 1, 25 | 'static_file' => 'core/components/' . PKG_NAME_LOWER . '/elements/chunks/chunk.' . $v['file'] . '.tpl', 26 | ), '', true, true); 27 | 28 | $chunks[] = $chunk; 29 | 30 | $BUILD_CHUNKS[$k] = file_get_contents($sources['source_core'] . '/elements/chunks/chunk.' . $v['file'] . '.tpl'); 31 | } 32 | 33 | unset($tmp); 34 | return $chunks; -------------------------------------------------------------------------------- /_build/data/transport.events.php: -------------------------------------------------------------------------------- 1 | $v) { 12 | /** @var modEvent $event */ 13 | $event = $modx->newObject('modEvent'); 14 | $event->fromArray(array( 15 | 'name' => $v, 16 | 'service' => 6, 17 | 'groupname' => PKG_NAME, 18 | ), '', true, true); 19 | $events[] = $event; 20 | } 21 | 22 | return $events; -------------------------------------------------------------------------------- /_build/data/transport.menu.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'description' => 'fileattach.menu_desc', 8 | 'permissions' => 'fileattach.totallist', 9 | 'action' => 'list' 10 | ), 11 | ); 12 | 13 | $i = 0; 14 | foreach ($tmp as $k => $v) { 15 | /* @var modMenu $menu */ 16 | $menu = $modx->newObject('modMenu'); 17 | $menu->fromArray(array_merge( 18 | array( 19 | 'namespace' => PKG_NAME_LOWER, 20 | 'text' => $k, 21 | 'parent' => 'components', 22 | 'menuindex' => $i, 23 | 'params' => '', 24 | 'handler' => '', 25 | ), $v 26 | ), '', true, true); 27 | 28 | $menus[] = $menu; 29 | $i++; 30 | } 31 | 32 | unset($action, $menu, $i); 33 | return $menus; -------------------------------------------------------------------------------- /_build/data/transport.plugins.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'file' => 'filestab', 8 | 'description' => '', 9 | 'events' => array( 10 | 'OnDocFormPrerender' => array(), 11 | 'OnEmptyTrash' => array() 12 | ) 13 | ) 14 | ); 15 | 16 | foreach ($tmp as $k => $v) { 17 | /* @avr modplugin $plugin */ 18 | $plugin = $modx->newObject('modPlugin'); 19 | $plugin->fromArray(array( 20 | 'name' => $k, 21 | 'category' => 0, 22 | 'description' => @$v['description'], 23 | 'plugincode' => getSnippetContent($sources['source_core'] . '/elements/plugins/plugin.' . $v['file'] . '.php'), 24 | 'static' => BUILD_PLUGIN_STATIC, 25 | 'source' => 1, 26 | 'static_file' => 'core/components/' . PKG_NAME_LOWER . '/elements/plugins/plugin.' . $v['file'] . '.php' 27 | ), '', true, true); 28 | 29 | $events = array(); 30 | if (!empty($v['events'])) { 31 | foreach ($v['events'] as $k2 => $v2) { 32 | /* @var modPluginEvent $event */ 33 | $event = $modx->newObject('modPluginEvent'); 34 | $event->fromArray(array_merge( 35 | array( 36 | 'event' => $k2, 37 | 'priority' => 0, 38 | 'propertyset' => 0, 39 | ), $v2 40 | ), '', true, true); 41 | $events[] = $event; 42 | } 43 | unset($v['events']); 44 | } 45 | 46 | if (!empty($events)) 47 | $plugin->addMany($events); 48 | 49 | $plugins[] = $plugin; 50 | } 51 | 52 | unset($tmp, $properties); 53 | return $plugins; -------------------------------------------------------------------------------- /_build/data/transport.policies.php: -------------------------------------------------------------------------------- 1 | array( 14 | 'description' => 'A policy for editing attached files to resources.', 15 | 'data' => '{"fileattach.totallist":true,"fileattach.doclist":true,"fileattach.download":true,"fileattach.list":true,"fileattach.remove":true}'), 16 | 'File Attach Download' => array( 17 | 'description' => 'A policy for downloading attached files to resources.', 18 | 'data' => '{"fileattach.download":true}'), 19 | 'File Attach Frontend' => array( 20 | 'description' => 'A policy for frontend uploading files to resources.', 21 | 'data' => '{"fileattach.download":true,"fileattach.list":true,"fileattach.remove":true}') 22 | ); 23 | 24 | foreach ($tmp as $k => $v) { 25 | /* @avr modplugin $plugin */ 26 | $policy = $modx->newObject('modAccessPolicy'); 27 | 28 | $policy->fromArray(array( 29 | 'name' => $k, 30 | 'parent' => 0, 31 | 'class' => '', 32 | 'lexicon' => PKG_NAME_LOWER . ':permissions', 33 | 'data' => @$v['data'], 34 | 'description' => @$v['description'] 35 | ), '', true, true); 36 | 37 | $policies[] = $policy; 38 | } 39 | 40 | unset($tmp, $template); 41 | return $policies; -------------------------------------------------------------------------------- /_build/data/transport.policytemplates.php: -------------------------------------------------------------------------------- 1 | newObject('modAccessPolicyTemplate'); 12 | $templates['1']->fromArray(array( 13 | 'id' => 1, 14 | 'name' => 'FileAttachTemplate', 15 | 'description' => 'A policy template for attached files containers.', 16 | 'lexicon' => 'fileattach:permissions', 17 | 'template_group' => 1, 18 | )); 19 | 20 | $permissions = include dirname(__FILE__).'/permissions/fileattach.policy.php'; 21 | 22 | if (is_array($permissions)) { 23 | $templates['1']->addMany($permissions); 24 | } else { 25 | $modx->log(modX::LOG_LEVEL_ERROR,'Could not load FileAttach Policy Template.'); 26 | } 27 | 28 | return $templates; -------------------------------------------------------------------------------- /_build/data/transport.settings.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'key' => 'fileattach.mediasource', 8 | 'name' => 'setting_fileattach.mediasource', 9 | 'description' => 'setting_fileattach.mediasource_desc', 10 | 'xtype' => 'modx-combo-source', 11 | 'lexicon' => 'fileattach:setting', 12 | 'area' => 'file', 13 | 'value' => 1 14 | ), 15 | 'files_path' => array( 16 | 'key' => 'fileattach.files_path', 17 | 'name' => 'setting_fileattach.files_path', 18 | 'description' => 'setting_fileattach.files_path_desc', 19 | 'xtype' => 'textfield', 20 | 'lexicon' => 'fileattach:setting', 21 | 'area' => 'file', 22 | 'value' => '/' 23 | ), 24 | 'templates' => array( 25 | 'key' => 'fileattach.templates', 26 | 'name' => 'setting_fileattach.templates', 27 | 'description' => 'setting_fileattach.templates_desc', 28 | 'xtype' => 'textfield', 29 | 'lexicon' => 'fileattach:setting', 30 | 'value' => '' 31 | ), 32 | 'user_folders' => array( 33 | 'key' => 'fileattach.user_folders', 34 | 'name' => 'setting_fileattach.user_folders', 35 | 'description' => 'setting_fileattach.user_folders_desc', 36 | 'xtype' => 'combo-boolean', 37 | 'lexicon' => 'fileattach:setting', 38 | 'area' => 'file', 39 | 'value' => false 40 | ), 41 | 'calchash' => array( 42 | 'key' => 'fileattach.calchash', 43 | 'name' => 'setting_fileattach.calchash', 44 | 'description' => 'setting_fileattach.calchash_desc', 45 | 'xtype' => 'combo-boolean', 46 | 'lexicon' => 'fileattach:setting', 47 | 'value' => false 48 | ), 49 | 'put_docid' => array( 50 | 'key' => 'fileattach.put_docid', 51 | 'name' => 'setting_fileattach.put_docid', 52 | 'description' => 'setting_fileattach.put_docid_desc', 53 | 'xtype' => 'combo-boolean', 54 | 'lexicon' => 'fileattach:setting', 55 | 'area' => 'file', 56 | 'value' => false 57 | ), 58 | 'private' => array( 59 | 'key' => 'fileattach.private', 60 | 'name' => 'setting_fileattach.private', 61 | 'description' => 'setting_fileattach.private_desc', 62 | 'xtype' => 'combo-boolean', 63 | 'lexicon' => 'fileattach:setting', 64 | 'area' => 'file', 65 | 'value' => false 66 | ), 67 | 'download' => array( 68 | 'key' => 'fileattach.download', 69 | 'name' => 'setting_fileattach.download', 70 | 'description' => 'setting_fileattach.download_desc', 71 | 'xtype' => 'combo-boolean', 72 | 'lexicon' => 'fileattach:setting', 73 | 'value' => true 74 | ), 75 | 'translit' => array( 76 | 'key' => 'fileattach.translit', 77 | 'name' => 'setting_fileattach.translit', 78 | 'description' => 'setting_fileattach.translit_desc', 79 | 'xtype' => 'combo-boolean', 80 | 'lexicon' => 'fileattach:setting', 81 | 'value' => false 82 | ), 83 | ); 84 | 85 | foreach ($tmp as $k => $v) { 86 | /* @var modSystemSetting $setting */ 87 | $setting = $modx->newObject('modSystemSetting'); 88 | $setting->fromArray(array_merge( 89 | array( 90 | 'key' => 'fileattach.' . $k, 91 | 'namespace' => PKG_NAME_LOWER, 92 | ), $v 93 | ), '', true, true); 94 | 95 | $settings[] = $setting; 96 | } 97 | 98 | unset($tmp); 99 | return $settings; 100 | -------------------------------------------------------------------------------- /_build/data/transport.snippets.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'file' => 'fileattach', 8 | 'description' => '', 9 | ), 10 | 'FileLink' => array( 11 | 'file' => 'filelink', 12 | 'description' => '', 13 | ), 14 | ); 15 | 16 | foreach ($tmp as $k => $v) { 17 | /* @avr modSnippet $snippet */ 18 | $snippet = $modx->newObject('modSnippet'); 19 | $snippet->fromArray(array( 20 | 'id' => 0, 21 | 'name' => $k, 22 | 'description' => @$v['description'], 23 | 'snippet' => getSnippetContent($sources['source_core'] . '/elements/snippets/snippet.' . $v['file'] . '.php'), 24 | 'static' => BUILD_SNIPPET_STATIC, 25 | 'source' => 1, 26 | 'static_file' => 'core/components/' . PKG_NAME_LOWER . '/elements/snippets/snippet.' . $v['file'] . '.php', 27 | ), '', true, true); 28 | 29 | $properties = include $sources['build'] . 'properties/properties.' . $v['file'] . '.php'; 30 | $snippet->setProperties($properties); 31 | 32 | $snippets[] = $snippet; 33 | } 34 | 35 | unset($tmp, $properties); 36 | return $snippets; -------------------------------------------------------------------------------- /_build/includes/functions.php: -------------------------------------------------------------------------------- 1 | ')); 13 | } 14 | 15 | 16 | /** 17 | * Recursive directory remove 18 | * 19 | * @param $dir 20 | */ 21 | function rrmdir($dir) { 22 | if (is_dir($dir)) { 23 | $objects = scandir($dir); 24 | 25 | foreach ($objects as $object) { 26 | if ($object != '.' && $object != '..') { 27 | if (filetype($dir . '/' . $object) == 'dir') { 28 | rrmdir($dir . '/' . $object); 29 | } else { 30 | unlink($dir . '/' . $object); 31 | } 32 | } 33 | } 34 | 35 | reset($objects); 36 | rmdir($dir); 37 | } 38 | } -------------------------------------------------------------------------------- /_build/properties/properties.fileattach.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'type' => 'textfield', 8 | 'value' => 'FileAttachTpl', 9 | ), 10 | 'sortBy' => array( 11 | 'type' => 'textfield', 12 | 'value' => 'name', 13 | ), 14 | 'sortDir' => array( 15 | 'type' => 'list', 16 | 'options' => array( 17 | array('text' => 'ASC', 'value' => 'ASC'), 18 | array('text' => 'DESC', 'value' => 'DESC'), 19 | ), 20 | 'value' => 'ASC' 21 | ), 22 | 'inline' => array( 23 | 'type' => 'combo-boolean', 24 | 'value' => false, 25 | ), 26 | 'limit' => array( 27 | 'type' => 'numberfield', 28 | 'value' => 0, 29 | ), 30 | 'offset' => array( 31 | 'type' => 'numberfield', 32 | 'value' => 0, 33 | ), 34 | 'totalVar' => array( 35 | 'type' => 'textfield', 36 | 'value' => 'total', 37 | ), 38 | 'outputSeparator' => array( 39 | 'type' => 'textfield', 40 | 'value' => "\n", 41 | ), 42 | 'toPlaceholder' => array( 43 | 'type' => 'combo-boolean', 44 | 'value' => false, 45 | ), 46 | 'resource' => array( 47 | 'type' => 'numberfield', 48 | 'value' => 0, 49 | ), 50 | 'makeUrl' => array( 51 | 'type' => 'combo-boolean', 52 | 'value' => true, 53 | ), 54 | 'privateUrl' => array( 55 | 'type' => 'combo-boolean', 56 | 'value' => false, 57 | ), 58 | 'showHASH' => array( 59 | 'type' => 'combo-boolean', 60 | 'value' => false, 61 | ), 62 | 'showSize' => array( 63 | 'type' => 'combo-boolean', 64 | 'value' => false, 65 | ), 66 | 'showExt' => array( 67 | 'type' => 'combo-boolean', 68 | 'value' => false, 69 | ), 70 | 'groups' => array( 71 | 'type' => 'textfield', 72 | 'value' => '', 73 | ), 74 | ); 75 | 76 | foreach ($tmp as $k => $v) { 77 | $properties[] = array_merge( 78 | array( 79 | 'name' => $k, 80 | 'desc' => PKG_NAME_LOWER . '.prop_' . $k, 81 | 'lexicon' => PKG_NAME_LOWER . ':properties', 82 | ), $v 83 | ); 84 | } 85 | 86 | return $properties; -------------------------------------------------------------------------------- /_build/properties/properties.filelink.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'type' => 'numberfield', 8 | 'value' => 0, 9 | ), 10 | 'groups' => array( 11 | 'type' => 'textfield', 12 | 'value' => '', 13 | ), 14 | ); 15 | 16 | foreach ($tmp as $k => $v) { 17 | $properties[] = array_merge( 18 | array( 19 | 'name' => $k, 20 | 'desc' => PKG_NAME_LOWER . '.prop_' . $k, 21 | 'lexicon' => PKG_NAME_LOWER . ':properties', 22 | ), $v 23 | ); 24 | } 25 | 26 | return $properties; -------------------------------------------------------------------------------- /_build/resolvers/resolve.chunks.php: -------------------------------------------------------------------------------- 1 | xpdo) { 4 | /** @var modX $modx */ 5 | $modx =& $object->xpdo; 6 | 7 | switch ($options[xPDOTransport::PACKAGE_ACTION]) { 8 | case xPDOTransport::ACTION_INSTALL: 9 | break; 10 | 11 | case xPDOTransport::ACTION_UPGRADE: 12 | if (!empty($options['chunks']) && !empty($options['update_chunks'])) { 13 | foreach ($options['update_chunks'] as $v) { 14 | if (!empty($options['chunks'][$v]) && $chunk = $modx->getObject('modChunk', array('name' => $v))) { 15 | $chunk->set('snippet', $options['chunks'][$v]); 16 | $chunk->save(); 17 | $modx->log(modX::LOG_LEVEL_INFO, 'Updated chunk "' . $v . '"'); 18 | } 19 | } 20 | } 21 | break; 22 | 23 | case xPDOTransport::ACTION_UNINSTALL: 24 | break; 25 | } 26 | } 27 | 28 | return true; -------------------------------------------------------------------------------- /_build/resolvers/resolve.policy.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, a simple commenting component for MODx Revolution. 8 | * 9 | * FileAttach is free software; you can redistribute it and/or modify it under the 10 | * terms of the GNU General Public License as published by the Free Software 11 | * Foundation; either version 2 of the License, or (at your option) any later 12 | * version. 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package fileattach 23 | */ 24 | /** 25 | * Auto-assign the FileAttachPolicy to the Administrator User Group 26 | * 27 | * @package fileattach 28 | * @subpackage build 29 | */ 30 | if ($object->xpdo) { 31 | switch ($options[xPDOTransport::PACKAGE_ACTION]) { 32 | case xPDOTransport::ACTION_INSTALL: 33 | case xPDOTransport::ACTION_UPGRADE: 34 | $modx =& $object->xpdo; 35 | $modelPath = $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/') . 'model/'; 36 | $modx->addPackage('fileattach', $modelPath); 37 | 38 | $modx->setLogLevel(modX::LOG_LEVEL_ERROR); 39 | 40 | /* assign policy to template */ 41 | $template = $transport->xpdo->getObject('modAccessPolicyTemplate', array('name' => 'FileAttachTemplate')); 42 | if (!$template) 43 | $modx->log(xPDO::LOG_LEVEL_ERROR,'[FileAttach] Could not find FileAttacTemplate Access Policy Template!'); 44 | 45 | $policyList = array('File Attach', 'File Attach Download', 'File Attach Frontend'); 46 | 47 | foreach ($policyList as $policyName) { 48 | $policy = $transport->xpdo->getObject('modAccessPolicy', array('name' => $policyName)); 49 | 50 | if ($policy) { 51 | $policy->set('template', $template->get('id')); 52 | $policy->save(); 53 | } else 54 | $modx->log(xPDO::LOG_LEVEL_ERROR,'[FileAttach] Could not find ' . $policyName . ' Access Policy!'); 55 | } 56 | 57 | /* assign policy to admin group */ 58 | $policy = $modx->getObject('modAccessPolicy', array('name' => 'File Attach')); 59 | 60 | $adminGroup = $modx->getObject('modUserGroup', array('name' => 'Administrator')); 61 | if ($policy && $adminGroup) { 62 | $access = $modx->getObject('modAccessContext', array( 63 | 'target' => 'mgr', 64 | 'principal_class' => 'modUserGroup', 65 | 'principal' => $adminGroup->get('id'), 66 | 'authority' => 9999, 67 | 'policy' => $policy->get('id'), 68 | )); 69 | if (!$access) { 70 | $access = $modx->newObject('modAccessContext'); 71 | $access->fromArray(array( 72 | 'target' => 'mgr', 73 | 'principal_class' => 'modUserGroup', 74 | 'principal' => $adminGroup->get('id'), 75 | 'authority' => 9999, 76 | 'policy' => $policy->get('id'), 77 | )); 78 | $access->save(); 79 | } 80 | } 81 | 82 | /* assign policy to anonymous group */ 83 | if (isset($options['allow_anonymous'])) { 84 | $policy = $modx->getObject('modAccessPolicy', array('name' => 'File Attach Download')); 85 | 86 | $access = $modx->getObject('modAccessContext', array( 87 | 'target' => 'web', 88 | 'principal_class' => 'modUserGroup', 89 | 'principal' => 0, 90 | 'authority' => 9999, 91 | 'policy' => $policy->get('id'), 92 | )); 93 | if (!$access) { 94 | $access = $modx->newObject('modAccessContext'); 95 | $access->fromArray(array( 96 | 'target' => 'web', 97 | 'principal_class' => 'modUserGroup', 98 | 'principal' => 0, 99 | 'authority' => 9999, 100 | 'policy' => $policy->get('id'), 101 | )); 102 | $access->save(); 103 | } 104 | } 105 | 106 | $modx->setLogLevel(modX::LOG_LEVEL_INFO); 107 | break; 108 | } 109 | } 110 | 111 | return true; -------------------------------------------------------------------------------- /_build/resolvers/resolve.setup.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation; either version 2 of the License, or (at your option) any later 13 | * version. 14 | * 15 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 16 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 17 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License along with 20 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 21 | * Suite 330, Boston, MA 02111-1307 USA 22 | * 23 | * @package fileattach 24 | */ 25 | 26 | $success = false; 27 | 28 | if ($object->xpdo) { 29 | switch ($options[xPDOTransport::PACKAGE_ACTION]) { 30 | case xPDOTransport::ACTION_UPGRADE: 31 | if (!isset($options['install_pack'])) { 32 | $modx =& $object->xpdo; 33 | if ($modx instanceof modX) 34 | $modx->removeExtensionPackage('fileattach'); 35 | } 36 | 37 | case xPDOTransport::ACTION_INSTALL: 38 | if (isset($options['install_pack'])) { 39 | /** @var modX $modx */ 40 | $modx =& $object->xpdo; 41 | $modelPath = $modx->getOption('fileattach.core_path'); 42 | if (empty($modelPath)) 43 | $modelPath = '[[++core_path]]components/fileattach/'; 44 | 45 | $modelPath = rtrim($modelPath, '/') . '/model/'; 46 | if ($modx instanceof modX) 47 | $modx->addExtensionPackage('fileattach', $modelPath); 48 | } 49 | 50 | $success = true; 51 | break; 52 | case xPDOTransport::ACTION_UNINSTALL: 53 | $modx =& $object->xpdo; 54 | if ($modx instanceof modX) 55 | $modx->removeExtensionPackage('fileattach'); 56 | 57 | $success = true; 58 | break; 59 | } 60 | } 61 | 62 | return $success; -------------------------------------------------------------------------------- /_build/resolvers/resolve.tables.php: -------------------------------------------------------------------------------- 1 | xpdo) { 4 | /** @var modX $modx */ 5 | $modx =& $object->xpdo; 6 | 7 | $modelPath = $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/') . 'model/'; 8 | $modx->addPackage('fileattach', $modelPath); 9 | $manager = $modx->getManager(); 10 | 11 | switch ($options[xPDOTransport::PACKAGE_ACTION]) { 12 | case xPDOTransport::ACTION_INSTALL: 13 | // Create tables 14 | $objects = array( 15 | 'FileItem', 'FileAttachMediaSource' 16 | ); 17 | foreach ($objects as $tmp) { 18 | $manager->createObjectContainer($tmp); 19 | } 20 | break; 21 | 22 | case xPDOTransport::ACTION_UPGRADE: 23 | // Upgrade DB scheme if there were older packages installed 24 | // Find latest installed version 25 | 26 | $c = $modx->newQuery('modTransportPackage'); 27 | $c->select(array('version_major', 'version_minor', 'version_patch')); 28 | $c->where(array( 29 | 'package_name' => 'FileAttach', 30 | 'installed:IS NOT' => NULL 31 | )); 32 | $c->sortby('version_major', 'DESC'); 33 | $c->sortby('version_minor', 'DESC'); 34 | $c->sortby('version_patch', 'DESC'); 35 | 36 | $package = $modx->getObject('modTransportPackage', $c); 37 | if ($package) { 38 | $oldLogLevel = $modx->getLogLevel(); 39 | $modx->setLogLevel(0); 40 | 41 | $version = 42 | $package->get('version_major') * 1000 + 43 | $package->get('version_minor') * 100 + 44 | $package->get('version_patch'); 45 | 46 | // Update tables 47 | if ($version < 1002) 48 | $manager->addField('FileItem', 'rank', array('after' => 'uid')); 49 | 50 | if ($version < 1007) { 51 | $manager->addField('FileItem', 'fid', array('after' => 'id')); 52 | $manager->addIndex('FileItem', 'fid'); 53 | } 54 | 55 | if ($version < 1011) { 56 | $manager->addField('FileItem', 'tag', array('after' => 'hash')); 57 | $manager->alterField('FileItem', 'hash'); 58 | } 59 | 60 | $modx->setLogLevel($oldLogLevel); 61 | } 62 | 63 | // Find old records with empty file ID 64 | $needID = $modx->getCollection('FileItem', array('fid' => '')); 65 | foreach ($needID as $item) { 66 | $item->set('fid', $item->generateName()); 67 | $item->save(); 68 | } 69 | 70 | break; 71 | 72 | case xPDOTransport::ACTION_UNINSTALL: 73 | break; 74 | } 75 | } 76 | 77 | return true; -------------------------------------------------------------------------------- /_build/setup.options.php: -------------------------------------------------------------------------------- 1 | getOption('extension_packages'); 7 | if ($value) { 8 | $exts = $modx->fromJSON($value); 9 | foreach ($exts as $idx => $extPack) { 10 | foreach ($extPack as $key => $opt) { 11 | if ($key == 'fileattach') { 12 | $installed = true; 13 | break; 14 | } 15 | } 16 | } 17 | } 18 | 19 | // Check if anonymous policy is installed 20 | $access = NULL; 21 | 22 | $policy = $modx->getObject('modAccessPolicy', array('name' => 'File Attach Download')); 23 | if ($policy) { 24 | $access = $modx->getObject('modAccessContext', array( 25 | 'target' => 'web', 26 | 'principal_class' => 'modUserGroup', 27 | 'principal' => 0, 28 | 'authority' => 9999, 29 | 'policy' => $policy->get('id') 30 | )); 31 | } 32 | 33 | switch ($options[xPDOTransport::PACKAGE_ACTION]) { 34 | case xPDOTransport::ACTION_INSTALL: 35 | case xPDOTransport::ACTION_UPGRADE: 36 | if ($modx->getOption('manager_language') == 'ru') { 37 | $output = ' 38 | Позволяет использовать файловый медиа источник

'; 39 | 40 | $output .= ($access)? 41 | 'Анонимным пользователям разрешено скачивание' : 42 | ''; 43 | } else { 44 | $output = ' 45 | This will allow to use media file source

'; 46 | 47 | $output .= ($access)? 48 | 'Anonymous users downloading allowed' : 49 | ''; 50 | } 51 | 52 | case xPDOTransport::ACTION_UNINSTALL: 53 | break; 54 | } 55 | 56 | return $output; 57 | -------------------------------------------------------------------------------- /assets/components/fileattach/connector.php: -------------------------------------------------------------------------------- 1 | getService('fileattach', 'FileAttach', $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/') . 'model/fileattach/'); 11 | $modx->lexicon->load('fileattach:default'); 12 | 13 | $key = $modx->context->get('key'); 14 | if ($modx->user->hasSessionContext($key)) 15 | $_SERVER['HTTP_MODAUTH'] = $_SESSION["modx.$key.user.token"]; 16 | else { 17 | define('MODX_REQP', false); 18 | $_SERVER['HTTP_MODAUTH'] = 0; 19 | } 20 | 21 | // handle request 22 | $corePath = $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/'); 23 | $path = $modx->getOption('processorsPath', $FileAttach->config, $corePath . 'processors/'); 24 | $modx->request->handleRequest(array( 25 | 'processors_path' => $path, 26 | 'location' => '', 27 | )); -------------------------------------------------------------------------------- /assets/components/fileattach/js/mgr/fileattach.js: -------------------------------------------------------------------------------- 1 | var FileAttach = function (config) { 2 | config = config || {}; 3 | FileAttach.superclass.constructor.call(this, config); 4 | }; 5 | Ext.extend(FileAttach, Ext.Component, { 6 | page: {}, window: {}, grid: {}, panel: {}, config: {}, utils: {} 7 | }); 8 | Ext.reg('fileattach', FileAttach); 9 | 10 | FileAttach = new FileAttach(); -------------------------------------------------------------------------------- /assets/components/fileattach/js/mgr/filestab.js: -------------------------------------------------------------------------------- 1 | Ext.onReady(function () { 2 | var mainPanel = Ext.getCmp("modx-panel-resource"); 3 | if (!mainPanel) return; 4 | 5 | if (mainPanel.config.record.id > 0) { 6 | FileAttach.config.docid = mainPanel.config.record.id; 7 | 8 | MODx.addTab("modx-resource-tabs", { 9 | title: _("files"), 10 | id: "files-tab", 11 | width: "95%", 12 | items: [{ 13 | xtype: "fileattach-grid-items", 14 | width: "95%" 15 | }] 16 | }); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /assets/components/fileattach/js/mgr/widgets/home.panel.js: -------------------------------------------------------------------------------- 1 | FileAttach.page.Home = function (config) { 2 | config = config || {}; 3 | Ext.applyIf(config, { 4 | components: [{ 5 | xtype: 'fileattach-panel-home', renderTo: 'fileattach-panel-home-div' 6 | }] 7 | }); 8 | FileAttach.page.Home.superclass.constructor.call(this, config); 9 | }; 10 | Ext.extend(FileAttach.page.Home, MODx.Component); 11 | Ext.reg('fileattach-page-home', FileAttach.page.Home); 12 | 13 | FileAttach.panel.Home = function (config) { 14 | config = config || {}; 15 | Ext.apply(config, { 16 | baseCls: 'modx-formpanel', 17 | layout: 'anchor', 18 | hideMode: 'offsets', 19 | style: {padding: '20px 15px'}, 20 | items: [{ 21 | html: '

' + _('fileattach') + '

', 22 | cls: 'modx-page-header', 23 | border: false, 24 | }, { 25 | layout: 'anchor', 26 | items: [{ 27 | html: _('fileattach.intro_msg'), 28 | cls: 'panel-desc', 29 | }, { 30 | xtype: 'fileattach-grid-items', 31 | cls: 'main-wrapper', 32 | }] 33 | }] 34 | }); 35 | FileAttach.panel.Home.superclass.constructor.call(this, config); 36 | }; 37 | Ext.extend(FileAttach.panel.Home, MODx.Panel); 38 | Ext.reg('fileattach-panel-home', FileAttach.panel.Home); 39 | -------------------------------------------------------------------------------- /assets/components/fileattach/js/mgr/widgets/items.grid.js: -------------------------------------------------------------------------------- 1 | // Helper boolean render 2 | FileAttach.utils.renderBoolean = function (value, props, row) { 3 | return value 4 | ? String.format('{0}', _('yes')) 5 | : String.format('{0}', _('no')); 6 | } 7 | 8 | // Helper title render 9 | FileAttach.utils.renderName = function (value, props, row) { 10 | return value + 11 | ((row.data['description'])? '
' + 12 | row.data['description'] + '' : ''); 13 | } 14 | 15 | FileAttach.window.UpdateItem = function (config) { 16 | config = config || {}; 17 | if (!config.id) { 18 | config.id = 'fileattach-item-window-update'; 19 | } 20 | Ext.applyIf(config, { 21 | title: _('update'), 22 | width: 550, 23 | autoHeight: true, 24 | url: FileAttach.config.connectorUrl, 25 | action: 'mgr/update', 26 | fields: this.getFields(config), 27 | keys: [{ 28 | key: Ext.EventObject.ENTER, shift: true, fn: function () { 29 | this.submit() 30 | }, scope: this}] 31 | }); 32 | 33 | FileAttach.window.UpdateItem.superclass.constructor.call(this, config); 34 | } 35 | 36 | Ext.extend(FileAttach.window.UpdateItem, MODx.Window, { 37 | calcHash: function (btn, e, row) { 38 | btn.hide(); 39 | MODx.Ajax.request({ 40 | url: this.config.url, 41 | params: { 42 | action: 'mgr/hash', 43 | id: this.config.record.object.id 44 | }, 45 | listeners: { 46 | success: { 47 | fn: function (r) { 48 | Ext.getCmp(this.config.id + '-hash').setValue(r.object.hash); 49 | Ext.getCmp(this.config.id + '-hash').show(); 50 | }, scope: this}, 51 | fail: { fn: function () { btn.show(); }, scope: this } 52 | } 53 | }); 54 | }, 55 | 56 | getFields: function (config) { 57 | var fields = [{ 58 | xtype: 'hidden', 59 | name: 'id', 60 | id: config.id + '-id', 61 | }, { 62 | xtype: 'textfield', 63 | fieldLabel: _('name'), 64 | name: 'name', 65 | id: config.id + '-name', 66 | anchor: '100%', 67 | allowBlank: false 68 | }, { 69 | xtype: 'textfield', 70 | fieldLabel: _('description'), 71 | name: 'description', 72 | id: config.id + '-description', 73 | anchor: '100%', 74 | }, { 75 | xtype: 'textfield', 76 | fieldLabel: _('fileattach.tag'), 77 | id: config.id + '-tag', 78 | name: 'tag', 79 | anchor: '100%' 80 | }, { 81 | xtype: 'statictextfield', 82 | fieldLabel: _('fileattach.hash'), 83 | id: config.id + '-hash', 84 | name: 'hash', 85 | hidden: (config.record.object.hash == ''), 86 | anchor: '100%' 87 | }, { 88 | xtype: 'statictextfield', 89 | fieldLabel: _('fileattach.fid'), 90 | name: 'fid', 91 | id: config.id + '-fid', 92 | anchor: '100%', 93 | }]; 94 | 95 | if (config.record.object.hash == '') 96 | fields.push([{ 97 | xtype: 'button', 98 | text: _('fileattach.calculate'), 99 | style: 'margin-top: 15px;', 100 | handler: this.calcHash, 101 | scope: this 102 | }]); 103 | 104 | fields.push([{ 105 | xtype: 'xcheckbox', 106 | id: config.id + '-private', 107 | boxLabel: _('private'), 108 | hideLabel: true, 109 | name: 'private' 110 | }]); 111 | 112 | if (FileAttach.config.docid > 0) 113 | fields.push({xtype: 'hidden', name: 'docid', id: config.id + '-docid'}); 114 | else { 115 | fields.unshift({ 116 | xtype: 'modx-combo', 117 | id: config.id + '-docid', 118 | fieldLabel: _('resource'), 119 | name: 'docid', 120 | hiddenName: 'docid', 121 | url: FileAttach.config.connectorUrl, 122 | baseParams: { 123 | action: 'mgr/searchres' 124 | }, 125 | fields: ['id','pagetitle','description'], 126 | displayField: 'pagetitle', 127 | anchor: '100%', 128 | pageSize: 10, 129 | editable: true, 130 | typeAhead: true, 131 | allowBlank: false, 132 | forceSelection: true, 133 | tpl: new Ext.XTemplate('
{pagetitle}', 134 | '
{description}
', '
') 135 | }); 136 | } 137 | 138 | return fields; 139 | } 140 | }); 141 | Ext.reg('fileattach-item-window-update', FileAttach.window.UpdateItem); 142 | 143 | FileAttach.grid.Items = function (config) { 144 | config = config || {}; 145 | if (!config.id) { 146 | config.id = 'fileattach-grid-items'; 147 | } 148 | this.sm = new Ext.grid.CheckboxSelectionModel(); 149 | Ext.applyIf(config, { 150 | url: FileAttach.config.connectorUrl, 151 | fields: this.getFields(config), 152 | columns: this.getColumns(config), 153 | ddText: _('fileattach.ddtext'), 154 | tbar: this.getTopBar(config), 155 | sm: this.sm, 156 | baseParams: { 157 | action: 'mgr/getlist', 158 | docid: FileAttach.config.docid 159 | }, 160 | listeners: { 161 | rowDblClick: function (grid, rowIndex, e) { 162 | var row = grid.store.getAt(rowIndex); 163 | this.updateItem(grid, e, row); 164 | }, 165 | sortchange: this.saveSort 166 | }, 167 | viewConfig: { 168 | forceFit: true, 169 | enableRowBody: true, 170 | autoFill: true, 171 | showPreview: true, 172 | scrollOffset: 0 173 | }, 174 | paging: true, 175 | remoteSort: true, 176 | autoHeight: true, 177 | }); 178 | 179 | // Enable D&D only in resource editor 180 | if (FileAttach.config.docid) 181 | Ext.applyIf(config, { 182 | plugins: [new Ext.ux.dd.GridDragDropRowOrder({ 183 | copy: false, 184 | scrollable: true, 185 | targetCfg: {}, 186 | listeners: { 187 | 'afterrowmove': {fn:this.onAfterRowMove, scope:this} 188 | } 189 | })] 190 | }); 191 | 192 | // Restore sort state 193 | var sortInfo = []; 194 | if (sortInfo = this.restoreSort()) { 195 | // Workaround for absence of sortInfo support 196 | config.baseParams.sort = sortInfo[0]; 197 | config.baseParams.dir = sortInfo[1]; 198 | 199 | config.sortBy = sortInfo[0]; 200 | config.sortDir = sortInfo[1]; 201 | } 202 | 203 | FileAttach.grid.Items.superclass.constructor.call(this, config); 204 | 205 | // Set sort arrow 206 | if (sortInfo.length > 0) 207 | this.store.setDefaultSort(sortInfo[0], sortInfo[1]); 208 | 209 | this.restoreColumn(); 210 | this.colModel.on('hiddenchange', this.saveColumn, this); 211 | 212 | // Clear selection on grid refresh 213 | this.store.on('load', function () { 214 | if (this._getSelectedIds().length) { 215 | this.getSelectionModel().clearSelections(); 216 | } 217 | }, this); 218 | } 219 | Ext.extend(FileAttach.grid.Items, MODx.grid.Grid, { 220 | windows: {}, 221 | 222 | // Item context menu 223 | getMenu: function (grid, rowIndex) { 224 | var menu = [ 225 | {handler: grid['downloadItem'], text: _('file_download')}, 226 | {handler: grid['updateItem'], text: _('update')}, 227 | {handler: grid['resetItem'], text: _('reset')}, 228 | '-', 229 | {handler: grid['removeItem'], text: _('remove')} 230 | ]; 231 | 232 | this.addContextMenuItem(menu); 233 | }, 234 | 235 | // Restore sort info to session storage 236 | restoreSort: function () { 237 | if (typeof(Storage) !== "undefined") { 238 | var sortInfo = sessionStorage.getItem('fa_sort' + ((FileAttach.config.docid > 0)? '_' + FileAttach.config.docid : '')); 239 | return (sortInfo)? sortInfo.split('|', 2) : false; 240 | } 241 | 242 | return false; 243 | }, 244 | 245 | // Save sort info to session storage 246 | saveSort: function (grid, sortInfo) { 247 | if (typeof(Storage) !== "undefined") { 248 | sessionStorage.setItem('fa_sort' + ((FileAttach.config.docid > 0)? '_' + FileAttach.config.docid : ''), 249 | sortInfo.field + "|" + sortInfo.direction); 250 | } 251 | }, 252 | 253 | // Restore column info from session storage 254 | restoreColumn: function () { 255 | if (typeof(Storage) !== "undefined") { 256 | var colInfo = sessionStorage.getItem('fa_col' + ((FileAttach.config.docid > 0)? '_' + FileAttach.config.docid : '')); 257 | if (colInfo != null) { 258 | var cols = colInfo.split(','); 259 | for (var i = 0; i < cols.length; i++) 260 | this.colModel.setHidden(i + 1, cols[i] == '0'); 261 | } 262 | } 263 | }, 264 | 265 | // Save column visibility to session storage 266 | saveColumn: function(colModel, colIndex, hidden) { 267 | if (typeof(Storage) !== "undefined") { 268 | var count = colModel.getColumnCount(false); 269 | var cols = []; 270 | for (var i = 1; i < count; i++) cols.push(colModel.isHidden(i)? 0 : 1); 271 | 272 | sessionStorage.setItem('fa_col' + ((FileAttach.config.docid > 0)? '_' + FileAttach.config.docid : ''), 273 | cols.join(',')); 274 | } 275 | }, 276 | 277 | // Edit item 278 | updateItem: function (btn, e, row) { 279 | if (typeof(row) != 'undefined') { 280 | this.menu.record = row.data; 281 | } 282 | else if (!this.menu.record) { 283 | return false; 284 | } 285 | var id = this.menu.record.id; 286 | 287 | MODx.Ajax.request({ 288 | url: this.config.url, 289 | params: { 290 | action: 'mgr/get', 291 | docid: FileAttach.config.docid, 292 | id: id 293 | }, 294 | listeners: { 295 | success: { 296 | fn: function (r) { 297 | var w = MODx.load({ 298 | xtype: 'fileattach-item-window-update', 299 | id: Ext.id(), 300 | record: r, 301 | listeners: { 302 | success: { fn: function () { this.refresh(); }, scope: this } 303 | } 304 | }); 305 | w.reset(); 306 | w.setValues(r.object); 307 | w.show(e.target); 308 | }, scope: this 309 | } 310 | } 311 | }); 312 | }, 313 | 314 | // Edit item access 315 | accessItem: function (act, btn, e) { 316 | var ids = this._getSelectedIds(); 317 | if (!ids.length) { 318 | return false; 319 | } 320 | 321 | MODx.Ajax.request({ 322 | url: this.config.url, 323 | params: { 324 | action: 'mgr/access', 325 | private: (act.name == 'close')? 1:0, 326 | ids: Ext.util.JSON.encode(ids), 327 | }, 328 | listeners: { 329 | success: { fn: function (r) { this.refresh(); }, scope: this }, 330 | failure: {fn: function (r) {}, scope: this} 331 | } 332 | }); 333 | 334 | return true; 335 | }, 336 | 337 | // Reset download count 338 | resetItem: function (act, btn, e) { 339 | var ids = this._getSelectedIds(); 340 | if (!ids.length) { 341 | return false; 342 | } 343 | MODx.msg.confirm({ 344 | title: ids.length > 1 345 | ? _('reset') 346 | : _('reset'), 347 | text: ids.length > 1 348 | ? _('fileattach.resets_confirm') 349 | : _('fileattach.reset_confirm'), 350 | url: this.config.url, 351 | params: { 352 | action: 'mgr/reset', 353 | ids: Ext.util.JSON.encode(ids), 354 | }, 355 | listeners: { 356 | success: { 357 | fn: function (r) { 358 | this.refresh(); 359 | }, scope: this 360 | } 361 | } 362 | }); 363 | return true; 364 | }, 365 | 366 | // Remove item 367 | removeItem: function (act, btn, e) { 368 | var ids = this._getSelectedIds(); 369 | if (!ids.length) { 370 | return false; 371 | } 372 | MODx.msg.confirm({ 373 | title: ids.length > 1 374 | ? _('remove') 375 | : _('remove'), 376 | text: ids.length > 1 377 | ? _('confirm_remove') 378 | : _('confirm_remove'), 379 | url: this.config.url, 380 | params: { 381 | action: 'mgr/remove', 382 | ids: Ext.util.JSON.encode(ids) 383 | }, 384 | listeners: { 385 | success: { 386 | fn: function (r) { 387 | this.refresh(); 388 | }, scope: this 389 | } 390 | } 391 | }); 392 | return true; 393 | }, 394 | 395 | // Download file 396 | downloadItem: function (act, btn, e) { 397 | var item = this._getSelected(); 398 | 399 | var filePath = MODx.config['fileattach.files_path'] + item['path'] + item['internal_name']; 400 | 401 | MODx.Ajax.request({ 402 | url: MODx.config.connector_url, 403 | params: { 404 | action: 'browser/file/download', 405 | file: filePath, 406 | wctx: MODx.ctx || '', 407 | source: MODx.config['fileattach.mediasource'] 408 | }, 409 | listeners: { 410 | 'success': { fn: function(r) { 411 | if (!Ext.isEmpty(r.object.url)) { 412 | location.href = MODx.config.connector_url + 413 | '?action=browser/file/download&download=1&file=' + 414 | filePath + '&HTTP_MODAUTH=' + MODx.siteId + 415 | '&source=' + MODx.config['fileattach.mediasource'] + '&wctx=' + MODx.ctx; 416 | } 417 | }, scope:this } 418 | } 419 | }); 420 | 421 | return true; 422 | }, 423 | 424 | // Show uploader dialog 425 | uploadFiles: function(btn,e) { 426 | if (!this.uploader) { 427 | aVer = MODx.config.version.split('.'); 428 | uploaddialog = ((aVer[0] == 2) && aVer[1] >= 3)? MODx.util.MultiUploadDialog.Dialog : Ext.ux.UploadDialog.Dialog; 429 | 430 | this.uploader = new uploaddialog({ 431 | title: _('upload'), 432 | url: this.config.url, 433 | base_params: { 434 | action: 'mgr/upload', 435 | docid: FileAttach.config.docid 436 | }, 437 | cls: 'ext-ux-uploaddialog-dialog modx-upload-window' 438 | }); 439 | this.uploader.on('hide', this.refresh,this); 440 | this.uploader.on('close', this.refresh,this); 441 | } 442 | 443 | // Automatically open picker 444 | this.uploader.show(btn); 445 | this.uploader.buttons[0].input_file.dom.click(); 446 | }, 447 | 448 | // Define visible fields 449 | getFields: function (config) { 450 | return ['id', 'name', 'description', 'docid', 'download', 'private', 'pagetitle', 'username', 'rank', 'tag']; 451 | }, 452 | 453 | // Define columns 454 | getColumns: function (config) { 455 | var columns = [this.sm, { 456 | header: _('fileattach.rank'), 457 | dataIndex: 'rank', 458 | hidden: true, 459 | sortable: FileAttach.config.docid > 0, 460 | width: 50 461 | }, { 462 | header: _('id'), 463 | dataIndex: 'id', 464 | sortable: true, 465 | width: 50 466 | }, { 467 | header: _('name'), 468 | dataIndex: 'name', 469 | sortable: true, 470 | width: 200, 471 | renderer: FileAttach.utils.renderName 472 | }, { 473 | header: _('fileattach.downloads'), 474 | dataIndex: 'download', 475 | width: 50, 476 | sortable: true, 477 | }, { 478 | header: _('private'), 479 | dataIndex: 'private', 480 | width: 50, 481 | sortable: true, 482 | renderer: FileAttach.utils.renderBoolean 483 | }, { 484 | header: _('tag'), 485 | dataIndex: 'tag', 486 | width: 50, 487 | hidden: true, 488 | sortable: true 489 | }]; 490 | 491 | if (!FileAttach.config.docid) 492 | columns.push({ 493 | header: _('resource'), 494 | dataIndex: 'pagetitle', 495 | sortable: true 496 | }, { 497 | header: _('user'), 498 | dataIndex: 'username', 499 | sortable: true 500 | }); 501 | 502 | return columns; 503 | }, 504 | 505 | // Form top bar 506 | getTopBar: function (config) { 507 | var fields = []; 508 | 509 | if (FileAttach.config.docid) 510 | fields.push({ 511 | xtype: 'button', 512 | cls: 'primary-button', 513 | text: _('upload'), 514 | handler: this.uploadFiles, 515 | scope: this 516 | }); 517 | 518 | fields.push({ 519 | xtype: 'splitbutton', 520 | text: _('remove'), 521 | menu: [{ 522 | name: 'open', 523 | text: _('fileattach.open'), 524 | handler: this.accessItem, 525 | scope: this 526 | }, { 527 | name: 'close', 528 | text: _('fileattach.private'), 529 | handler: this.accessItem, 530 | scope: this 531 | }, '-', { 532 | text: _('fileattach.reset'), 533 | handler: this.resetItem, 534 | scope: this 535 | }, { 536 | text: _('remove'), 537 | handler: this.removeItem, 538 | scope: this 539 | }], 540 | text: _('bulk_actions') 541 | }, '->', { 542 | xtype: 'textfield', 543 | name: 'uid', 544 | width: 200, 545 | id: config.id + '-search-uid-field', 546 | emptyText: _('user'), 547 | listeners: { 548 | render: { 549 | fn: function (tf) { 550 | tf.getEl().addKeyListener(Ext.EventObject.ENTER, 551 | function () { this._doSearch(tf); }, this); 552 | }, scope: this 553 | } 554 | } 555 | }, { 556 | xtype: 'textfield', 557 | name: 'query', 558 | width: 200, 559 | id: config.id + '-search-field', 560 | emptyText: _('search'), 561 | listeners: { 562 | render: { 563 | fn: function (tf) { 564 | tf.getEl().addKeyListener(Ext.EventObject.ENTER, 565 | function () { this._doSearch(tf); }, this); 566 | }, scope: this 567 | } 568 | } 569 | }, { 570 | xtype: 'button', 571 | id: config.id + '-search-clear', 572 | text: '', 573 | listeners: { 574 | click: {fn: this._clearSearch, scope: this} 575 | } 576 | }); 577 | 578 | return fields; 579 | }, 580 | 581 | // Header button handler 582 | onClick: function (e) { 583 | var elem = e.getTarget(); 584 | if (elem.nodeName == 'BUTTON') { 585 | var row = this.getSelectionModel().getSelected(); 586 | if (typeof(row) != 'undefined') { 587 | var action = elem.getAttribute('action'); 588 | if (action == 'showMenu') { 589 | var ri = this.getStore().find('id', row.id); 590 | return this._showMenu(this, ri, e); 591 | } 592 | else if (typeof this[action] === 'function') { 593 | this.menu.record = row.data; 594 | return this[action](this, e); 595 | } 596 | } 597 | } 598 | return this.processEvent('click', e); 599 | }, 600 | 601 | // Get first selected record 602 | _getSelected: function () { 603 | var selected = this.getSelectionModel().getSelections(); 604 | 605 | for (var i in selected) { 606 | if (!selected.hasOwnProperty(i)) continue; 607 | return selected[i].json; 608 | } 609 | 610 | return null; 611 | }, 612 | 613 | // Get list of selected ID 614 | _getSelectedIds: function () { 615 | var ids = []; 616 | var selected = this.getSelectionModel().getSelections(); 617 | 618 | for (var i in selected) { 619 | if (!selected.hasOwnProperty(i)) continue; 620 | ids.push(selected[i]['id']); 621 | } 622 | 623 | return ids; 624 | }, 625 | 626 | // Perform store update with search query 627 | _doSearch: function (tf, nv, ov) { 628 | if (tf.name == 'query') 629 | this.getStore().baseParams.query = tf.getValue(); 630 | 631 | if (tf.name == 'uid') 632 | this.getStore().baseParams.uid = tf.getValue(); 633 | this.getBottomToolbar().changePage(1); 634 | this.refresh(); 635 | }, 636 | 637 | // Reset search query 638 | _clearSearch: function (btn, e) { 639 | this.getStore().baseParams.query = ''; 640 | this.getStore().baseParams.uid = ''; 641 | Ext.getCmp(this.config.id + '-search-uid-field').setValue(''); 642 | Ext.getCmp(this.config.id + '-search-field').setValue(''); 643 | this.getBottomToolbar().changePage(1); 644 | this.refresh(); 645 | }, 646 | 647 | // Handle changing item order with dragging 648 | onAfterRowMove: function(dt,sri,ri,sels) { 649 | var s = this.getStore(); 650 | var sourceRec = s.getAt(sri); 651 | var belowRec = s.getAt(ri); 652 | var total = s.getTotalCount(); 653 | var upd = {}; 654 | 655 | sourceRec.set('rank', sri); 656 | sourceRec.commit(); 657 | upd[sourceRec.get('id')] = sri; 658 | 659 | var brec; 660 | for (var x = (ri - 1); x < total; x++) { 661 | brec = s.getAt(x); 662 | if (brec) { 663 | brec.set('rank', x); 664 | brec.commit(); 665 | upd[brec.get('id')] = x; 666 | } 667 | } 668 | 669 | MODx.Ajax.request({ 670 | url: this.config.url, 671 | params: { 672 | action: 'mgr/rank', 673 | rank: Ext.util.JSON.encode(upd), 674 | } 675 | }); 676 | 677 | return true; 678 | } 679 | }); 680 | Ext.reg('fileattach-grid-items', FileAttach.grid.Items); -------------------------------------------------------------------------------- /core/components/fileattach/controllers/list.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Class FileattachManageManagerController 27 | */ 28 | class FileattachListManagerController extends modExtraManagerController { 29 | /** @var FileAttach $FileAttach */ 30 | public $FileAttach; 31 | 32 | 33 | /** 34 | * @return void 35 | */ 36 | public function initialize() { 37 | $corePath = $this->modx->getOption('fileattach.core_path', null, $this->modx->getOption('core_path') . 'components/fileattach/'); 38 | require_once $corePath . 'model/fileattach/fileattach.class.php'; 39 | 40 | $this->FileAttach = new FileAttach($this->modx); 41 | $this->addJavascript($this->FileAttach->config['jsUrl'] . 'mgr/fileattach.js'); 42 | $this->addHtml(''); 45 | 46 | parent::initialize(); 47 | } 48 | 49 | 50 | /** 51 | * @return void 52 | */ 53 | public function loadCustomCssJs() { 54 | $this->addJavascript($this->FileAttach->config['jsUrl'] . 'mgr/widgets/items.grid.js'); 55 | $this->addJavascript($this->FileAttach->config['jsUrl'] . 'mgr/widgets/home.panel.js'); 56 | $this->addHtml(''); 61 | } 62 | 63 | 64 | /** 65 | * @return null|string 66 | */ 67 | public function getPageTitle() { 68 | return $this->modx->lexicon('fileattach'); 69 | } 70 | 71 | 72 | /** 73 | * @return array 74 | */ 75 | public function getLanguageTopics() { 76 | return array('fileattach:default'); 77 | } 78 | 79 | 80 | /** 81 | * @return string 82 | */ 83 | public function getTemplateFile() { 84 | return $this->FileAttach->config['templatesPath'] . 'home.tpl'; 85 | } 86 | 87 | 88 | /** 89 | * @return bool 90 | */ 91 | public function checkPermissions() { return true; } 92 | } 93 | -------------------------------------------------------------------------------- /core/components/fileattach/docs/changelog.txt: -------------------------------------------------------------------------------- 1 | Changelog for FileAttach. 2 | 3 | 1.0.11pl 4 | ============== 5 | - Fix/update media source 6 | - Add tag support 7 | - Add extension filter 8 | 9 | 1.0.10pl4 10 | ============== 11 | - Add internal file translit support 12 | - Configuration keys put to file category 13 | 14 | 1.0.10pl3 15 | ============== 16 | - Make menu router-based, enhances compatibility with 2.3+ 17 | 18 | 1.0.10pl2 19 | ============== 20 | - Add file download in manager 21 | 22 | 1.0.10pl1 23 | ============== 24 | - Add support for pagination with new options: totalVar, offset 25 | 26 | 1.0.10 27 | ============== 28 | - Add system event 'faOnRemove' 29 | - Reformat table view 30 | - Remove unneeded JS objects 31 | - Fix typos, update doc URLs 32 | 33 | 1.0.9 34 | ============== 35 | - Compatibility with MODx >=2.5.2 36 | - Fix MediaSource error with MySQL 5.7 ONLY_FULL_GROUP_BY SQL Mode 37 | - Add download range support, download continuation 38 | 39 | 1.0.8 pl1 40 | ============== 41 | - Remember column sort state in session 42 | - Remember column visibility in session 43 | - Make rank column sortable in resource editor 44 | - Fix button captions / localization 45 | - Reformat code 46 | 47 | 1.0.8 48 | ============== 49 | - Fix margins in panels 50 | - Optimize plugin 51 | - Code cleanup and reformat 52 | 53 | 1.0.7 pl1 54 | ============== 55 | - Add file cleanup on resource removal 56 | - Optimize download processor performance 57 | 58 | 1.0.7 59 | ============== 60 | - Now files are available by unique string file ID 61 | - Add ability to restrict link list access with groups 62 | - Automatically open picker after upload button is clicked 63 | 64 | 1.0.6 65 | ============== 66 | - Add frontend processors 67 | - Add new policy for frontend uploader 68 | - Following system upload file type list 69 | - Don't double save on update 70 | 71 | 1.0.5 pl1 72 | ============== 73 | - Add ability to use extension placeholder 74 | 75 | 1.0.5 76 | ============== 77 | - Add ability to allow anonymous download 78 | - Fix snippet arguments typo 79 | 80 | 1.0.4 81 | ============== 82 | - DB scheme enhance 83 | - Add SQLSrv support 84 | 85 | 1.0.3 86 | ============== 87 | - Add compatibility with MODx v2.2 88 | - Snippet fix config loading 89 | - Enhance media source: 90 | - Extension distinction 91 | - Display thumbnails 92 | 93 | 1.0.2 94 | ============== 95 | - Add download option 96 | - Add rank field in model 97 | - Add ability to manually rearrange order 98 | 99 | 1.0.1 100 | ============== 101 | - Add ability to hash file if it didn't at upload 102 | - Add showSize option to snippet 103 | - Rewritten download processor 104 | - Updated FileItem model 105 | - Add filter for templates in document lister 106 | - UI editor rearrange 107 | 108 | 1.0.0 109 | ============== 110 | - Initial release 111 | -------------------------------------------------------------------------------- /core/components/fileattach/docs/license.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, June 2007 3 | 4 | Read full version at: 5 | http://www.gnu.org/licenses/gpl-3.0.en.html 6 | -------------------------------------------------------------------------------- /core/components/fileattach/docs/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------- 2 | FileAttach 3 | -------------------- 4 | Author: Vitaly Chekryzhev <13hakta@gmail.com> 5 | -------------------- 6 | 7 | File attach/upload tool for MODx Revolution. 8 | 9 | Feel free to suggest ideas/improvements/bugs on GitHub: 10 | http://github.com/13hakta/FileAttach/issues 11 | 12 | Official docs: 13 | http://13hakta.ru/blog/fileattach-en.html (English) 14 | http://13hakta.ru/blog/fileattach.html (Russian) 15 | -------------------------------------------------------------------------------- /core/components/fileattach/elements/chunks/chunk.item.tpl: -------------------------------------------------------------------------------- 1 |

[[+description:notempty=`[[+description]]
`]] 2 | [[+name]] [[+download]] 3 | [[+size:notempty=`
Size: [[+size]] bytes`]] 4 | [[+ext:notempty=`
Type: `]] 5 | [[+timestamp:notempty=`
Date: [[+timestamp:date=`%d.%m.%Y %H:%M`]]`]] 6 | [[+hash:notempty=`
SHA1: [[+hash]]`]]

7 | -------------------------------------------------------------------------------- /core/components/fileattach/elements/plugins/plugin.filestab.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | switch ($modx->event->name) { 26 | // Add a custom tab to the MODX create/edit resource pages 27 | case 'OnDocFormPrerender': 28 | 29 | // Check access 30 | if (!$modx->hasPermission('fileattach.doclist')) return; 31 | 32 | // Skip form building when resource template is not in permitted list 33 | $templates = $modx->getOption('fileattach.templates'); 34 | 35 | if ($templates != '') { 36 | $templatelist = explode(',', $templates); 37 | $template = is_object($resource)? $resource->get('template') : 0; 38 | if (!in_array($template, $templatelist)) return; 39 | } 40 | 41 | $modx->controller->addLexiconTopic('fileattach:default'); 42 | 43 | $corePath = $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/'); 44 | require_once $corePath . 'model/fileattach/fileattach.class.php'; 45 | 46 | $modx->FileAttach = new FileAttach($modx); 47 | $modx->controller->addJavascript($modx->FileAttach->config['jsUrl'] . 'mgr/fileattach.js'); 48 | $modx->controller->addJavascript($modx->FileAttach->config['jsUrl'] . 'mgr/widgets/items.grid.js'); 49 | $modx->controller->addLastJavascript($modx->FileAttach->config['jsUrl'] . 'mgr/filestab.js'); 50 | $modx->controller->addHtml(''); 51 | 52 | break; 53 | 54 | // Remove attached files to resources 55 | case 'OnEmptyTrash': 56 | // Load service 57 | if (!$FileAttach = $modx->getService('fileattach', 'FileAttach', 58 | $modx->getOption('fileattach.core_path', 59 | null, 60 | $modx->getOption('core_path') . 'components/fileattach/') . 'model/fileattach/')) { 61 | $modx->log(xPDO::LOG_LEVEL_ERROR, 'Could not load FileAttach class OnEmptyTrash!'); 62 | return; 63 | } 64 | 65 | foreach ($ids as &$id) { 66 | $c = $modx->newQuery('FileItem'); 67 | $c->where(array('docid' => $id)); 68 | 69 | $iter = $modx->getIterator('FileItem', $c); 70 | foreach ($iter as $item) $item->remove(); 71 | } 72 | 73 | break; 74 | } -------------------------------------------------------------------------------- /core/components/fileattach/elements/snippets/snippet.fileattach.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** @var array $scriptProperties */ 26 | /** @var FileAttach $FileAttach */ 27 | if (!$FileAttach = $modx->getService('fileattach', 'FileAttach', $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/') . 'model/fileattach/', $scriptProperties)) { 28 | return 'Could not load FileAttach class!'; 29 | } 30 | 31 | // Get script options 32 | $tpl = $modx->getOption('tpl', $scriptProperties, 'FileItemTpl'); 33 | $sortby = $modx->getOption('sortBy', $scriptProperties, 'name'); 34 | $sortdir = $modx->getOption('sortDir', $scriptProperties, 'ASC'); 35 | $inline = $modx->getOption('inline', $scriptProperties, false); 36 | $limit = $modx->getOption('limit', $scriptProperties, 0); 37 | $outputSeparator = $modx->getOption('outputSeparator', $scriptProperties, "\n"); 38 | $toPlaceholder = $modx->getOption('toPlaceholder', $scriptProperties, false); 39 | $resource = $modx->getOption('resource', $scriptProperties, 0); 40 | $makeUrl = $modx->getOption('makeUrl', $scriptProperties, true); 41 | $privateUrl = $modx->getOption('privateUrl', $scriptProperties, false); 42 | $showHASH = $modx->getOption('showHASH', $scriptProperties, false); 43 | $showSize = $modx->getOption('showSize', $scriptProperties, false); 44 | $showExt = $modx->getOption('showExt', $scriptProperties, false); 45 | $showTime = $modx->getOption('showTime', $scriptProperties, false); 46 | $ext = $modx->getOption('ext', $scriptProperties, ''); 47 | $tag = $modx->getOption('tag', $scriptProperties, ''); 48 | $groups = $modx->getOption('groups', $scriptProperties, ''); 49 | 50 | $offset = $modx->getOption('offset', $scriptProperties, 0); 51 | $totalVar = $modx->getOption('totalVar', $scriptProperties, 'total'); 52 | 53 | // Check access 54 | if ($groups != '') { 55 | // Forbid access for non-authorized visitor 56 | if (empty($modx->user)) return; 57 | 58 | $accessGroups = explode(',', $groups); 59 | 60 | // Argument set erroneously 61 | if (empty($accessGroups)) return; 62 | 63 | $accessGroups = array_map('trim', $accessGroups); 64 | 65 | if (!$modx->user->isMember($accessGroups)) return; 66 | } 67 | 68 | if ($makeUrl) { 69 | if (!$privateUrl || $showSize) { 70 | // Get base URLs 71 | $mediaSource = $modx->getOption('fileattach.mediasource', null, 1); 72 | 73 | $ms = $modx->getObject('sources.modMediaSource', array('id' => $mediaSource)); 74 | $ms->initialize(); 75 | 76 | $files_path = $modx->getOption('fileattach.files_path'); 77 | $public_url = $ms->getBaseUrl() . $files_path; 78 | $docs_path = $ms->getBasePath() . $files_path; 79 | } 80 | 81 | $private_url = $modx->getOption('fileattach.assets_url', null, $modx->getOption('assets_url')) . 'components/fileattach/'; 82 | $private_url .= 'connector.php?action=web/download&ctx=' . $modx->context->key; 83 | 84 | if ($inline) 85 | $private_url .= '&inline=1'; 86 | 87 | $private_url .= '&fid='; 88 | } 89 | 90 | // Build query 91 | $c = $modx->newQuery('FileItem'); 92 | 93 | if ($showHASH) 94 | $c->select($modx->getSelectColumns('FileItem', 'FileItem')); 95 | else 96 | $c->select($modx->getSelectColumns('FileItem', 'FileItem', '', array('hash'), true)); 97 | 98 | $c->where(array('docid' => ($resource > 0)? $resource : $modx->resource->get('id'))); 99 | 100 | if ($tag != '') 101 | $c->where(array('tag' => $tag)); 102 | 103 | if (!empty($limit)) { 104 | $total = $modx->getCount('FileItem', $c); 105 | $modx->setPlaceholder($totalVar, $total); 106 | } 107 | 108 | if (!empty($limit)) $c->limit($limit, $offset); 109 | $c->sortby($sortby, $sortdir); 110 | 111 | $items = $modx->getIterator('FileItem', $c); 112 | 113 | // Iterate through items 114 | $list = array(); 115 | /** @var FileItem $item */ 116 | foreach ($items as $item) { 117 | $item->source = $ms; 118 | $item->files_path = $files_path; 119 | 120 | $itemArr = $item->toArray(); 121 | 122 | if ($makeUrl) { 123 | if ($itemArr['private'] || $privateUrl) 124 | $itemArr['url'] = $private_url . $itemArr['fid']; 125 | else 126 | $itemArr['url'] = $public_url . $itemArr['path'] . $itemArr['name']; 127 | } 128 | 129 | if ($showSize) 130 | $itemArr['size'] = $item->getSize(); 131 | 132 | if ($showTime) 133 | $itemArr['timestamp'] = filectime($item->getFullPath()); 134 | 135 | if ($showExt) { 136 | $itemArr['ext'] = strtolower( 137 | pathinfo($itemArr['name'], PATHINFO_EXTENSION)); 138 | 139 | if (($ext != '') && ($ext != $itemArr['ext'])) continue; 140 | } 141 | 142 | $list[] = $modx->getChunk($tpl, $itemArr); 143 | } 144 | 145 | // Output 146 | $output = implode($outputSeparator, $list); 147 | if (!empty($toPlaceholder)) { 148 | // If using a placeholder, output nothing and set output to specified placeholder 149 | $modx->setPlaceholder($toPlaceholder, $output); 150 | 151 | return ''; 152 | } 153 | 154 | return $output; 155 | -------------------------------------------------------------------------------- /core/components/fileattach/elements/snippets/snippet.filelink.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** @var array $scriptProperties */ 26 | /** @var FileAttach $FileAttach */ 27 | if (!$FileAttach = $modx->getService('fileattach', 'FileAttach', $modx->getOption('fileattach.core_path', null, $modx->getOption('core_path') . 'components/fileattach/') . 'model/fileattach/', $scriptProperties)) { 28 | return 'Could not load FileAttach class!'; 29 | } 30 | 31 | // Get script options 32 | $fid = $modx->getOption('fid', $scriptProperties, 0); 33 | $groups = $modx->getOption('groups', $scriptProperties, ''); 34 | 35 | // Check access 36 | if ($groups != '') { 37 | // Forbid access for non-authorized visitor 38 | if (empty($modx->user)) return; 39 | 40 | $accessGroups = explode(',', $groups); 41 | 42 | // Argument set erroneously 43 | if (empty($accessGroups)) return; 44 | 45 | $accessGroups = array_map('trim', $accessGroups); 46 | 47 | if (!$modx->user->isMember($accessGroups)) return; 48 | } 49 | 50 | // Build query 51 | $item = $modx->getObject('FileItem', array('id' => $fid, 'docid' => $modx->resource->get('id'))); 52 | 53 | $itemArr = $item->toArray(); 54 | 55 | if ($itemArr['private']) { 56 | $private_url = $modx->getOption('fileattach.assets_url', null, $modx->getOption('assets_url')) . 57 | 'components/fileattach/connector.php?action=web/download&ctx=' . 58 | $modx->context->key . '&inline=1&fid='; 59 | 60 | $itemArr['url'] = $private_url . $itemArr['fid']; 61 | } else 62 | $itemArr['url'] = $public_url . $itemArr['path'] . $itemArr['name']; 63 | 64 | return $itemArr['url']; 65 | -------------------------------------------------------------------------------- /core/components/fileattach/elements/templates/home.tpl: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /core/components/fileattach/lexicon/en/default.inc.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * The base class for FileAttach. 27 | */ 28 | class FileAttach { 29 | /* @var modX $modx */ 30 | public $modx; 31 | 32 | /** 33 | * @param modX $modx 34 | * @param array $config 35 | */ 36 | function __construct(modX &$modx, array $config = array()) { 37 | $this->modx =& $modx; 38 | 39 | $corePath = $this->modx->getOption('fileattach.core_path', $config, $this->modx->getOption('core_path') . 'components/fileattach/'); 40 | $assetsUrl = $this->modx->getOption('fileattach.assets_url', $config, $this->modx->getOption('assets_url') . 'components/fileattach/'); 41 | $connectorUrl = $assetsUrl . 'connector.php'; 42 | 43 | $this->config = array_merge(array( 44 | 'assetsUrl' => $assetsUrl, 45 | 'jsUrl' => $assetsUrl . 'js/', 46 | 'connectorUrl' => $connectorUrl, 47 | 48 | 'corePath' => $corePath, 49 | 'modelPath' => $corePath . 'model/', 50 | 'chunksPath' => $corePath . 'elements/chunks/', 51 | 'templatesPath' => $corePath . 'elements/templates/', 52 | 'chunkSuffix' => '.chunk.tpl', 53 | 'snippetsPath' => $corePath . 'elements/snippets/', 54 | 'processorsPath' => $corePath . 'processors/' 55 | ), $config); 56 | 57 | $this->modx->addPackage('fileattach', $this->config['modelPath']); 58 | $this->modx->lexicon->load('fileattach:default'); 59 | } 60 | } -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/fileattachmediasource.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | class FileAttachMediaSource extends modMediaSource implements modMediaSourceInterface { 26 | /** @var FileAttach $fileattach */ 27 | public $fileattach; 28 | 29 | /** @var string $files_path */ 30 | private $files_path; 31 | 32 | /** @var int $parentSourceID */ 33 | private $parentSourceID; 34 | 35 | 36 | /** 37 | * Initialize the source, preparing it for usage. 38 | * 39 | * @return boolean 40 | */ 41 | public function initialize() { 42 | $this->fileattach = $this->xpdo->getService('fileattach', 'FileAttach', $this->xpdo->getOption('fileattach.core_path', null, $this->xpdo->getOption('core_path') . 'components/fileattach/') . 'model/fileattach/'); 43 | if (!($this->fileattach instanceof FileAttach)) 44 | return false; 45 | 46 | $this->parentSourceID = $this->xpdo->getOption('fileattach.mediasource', null, 1); 47 | $this->files_path = $this->xpdo->getOption('fileattach.files_path'); 48 | 49 | $this->xpdo->lexicon->load('fileattach:default', 'fileattach:source'); 50 | 51 | return true; 52 | } 53 | 54 | 55 | /** 56 | * Return an array of containers at this current level in the container structure. Used for the tree 57 | * navigation on the files tree. 58 | * 59 | * @param string $path 60 | * @return array 61 | */ 62 | public function getContainerList($path) { 63 | $properties = $this->getPropertyList(); 64 | $list = array(); 65 | 66 | if ($path == '/') { 67 | $c = $this->xpdo->newQuery('modResource'); 68 | 69 | $c->select('modResource.id,modResource.pagetitle'); 70 | $c->rightJoin('FileItem', 'FileItem', 'modResource.id=FileItem.docid'); 71 | $c->sortby('modResource.pagetitle', 'ASC'); 72 | $c->groupby('modResource.id'); 73 | 74 | $resources = $this->xpdo->getCollection('modResource', $c); 75 | /** @var modResource $resource */ 76 | foreach ($resources as $resource) { 77 | $list[] = array( 78 | 'id' => $resource->get('id'), 79 | 'text' => $resource->get('pagetitle') . ' (' . $resource->get('id') . ')', 80 | 'iconCls' => 'icon icon-folder', 81 | 'leaf' => false 82 | ); 83 | } 84 | 85 | return $list; 86 | } else { 87 | $id = (int)$path; 88 | 89 | /* get items */ 90 | $c = $this->xpdo->newQuery('FileItem'); 91 | $c->sortby('name', 'ASC'); 92 | $c->where(array('docid' => $id)); 93 | 94 | $items = $this->xpdo->getCollection('FileItem', $c); 95 | 96 | $t_description = $this->xpdo->lexicon('description'); 97 | $t_download = $this->xpdo->lexicon('fileattach.downloads'); 98 | $t_size = $this->xpdo->lexicon('fileattach.size'); 99 | $t_hash = $this->xpdo->lexicon('fileattach.hash'); 100 | 101 | /** @var FileItem $item */ 102 | foreach ($items as $item) { 103 | $ext = strtolower(pathinfo($item->get('internal_name'), PATHINFO_EXTENSION)); 104 | 105 | $tip = $t_description . ': ' . $item->get('description') . '
' . 106 | $t_download . ': ' . $item->get('download') . '
' . 107 | $t_size . ': ' . $item->getSize() . '
' . 108 | $t_hash . ': ' . $item->get('hash'); 109 | 110 | $list[] = array( 111 | 'id' => $item->get('id'), 112 | 'text' => $item->get('name'), 113 | 'iconCls' => 'icon icon-file icon-' . $ext . (($item->get('private'))? ' icon-access' : ''), 114 | 'qtip' => $tip, 115 | 'leaf' => true 116 | ); 117 | } 118 | 119 | return $list; 120 | } 121 | } 122 | 123 | 124 | /** 125 | * Return a detailed list of objects in a specific path. Used for thumbnails in the Browser. 126 | * 127 | * @param string $path 128 | * @return array 129 | */ 130 | public function getObjectsInContainer($path) { 131 | // Initialize config 132 | $properties = $this->getPropertyList(); 133 | $list = array(); 134 | 135 | $modAuth = $this->xpdo->user->getUserToken($this->xpdo->context->get('key')); 136 | 137 | $thumbnailType = $this->getOption('thumbnailType', $properties, 'png'); 138 | $thumbnailQuality = $this->getOption('thumbnailQuality', $properties, 90); 139 | $thumbWidth = $this->xpdo->context->getOption('filemanager_thumb_width', 100); 140 | $thumbHeight = $this->xpdo->context->getOption('filemanager_thumb_height', 80); 141 | $imageWidth = $this->ctx->getOption('filemanager_image_width', 800); 142 | $imageHeight = $this->ctx->getOption('filemanager_image_height', 600); 143 | 144 | $thumb_default = $this->xpdo->context->getOption('manager_url', MODX_MANAGER_URL) . 'templates/default/images/restyle/nopreview.jpg'; 145 | $thumbUrl = $this->xpdo->context->getOption('connectors_url', MODX_CONNECTORS_URL) . 'system/phpthumb.php?'; 146 | 147 | $imagesExts = $this->getOption('imageExtensions', $properties, 'jpg,jpeg,png,gif'); 148 | $imagesExts = explode(',', $imagesExts); 149 | 150 | if ($path != '/') { 151 | $thumb = $this->ctx->getOption('manager_url', MODX_MANAGER_URL).'templates/default/images/restyle/nopreview.jpg'; 152 | 153 | $id = (int)$path; 154 | 155 | /* get items */ 156 | $c = $this->xpdo->newQuery('FileItem'); 157 | $c->sortby('name', 'ASC'); 158 | $c->where(array('docid' => $id)); 159 | 160 | $items = $this->xpdo->getCollection('FileItem', $c); 161 | 162 | /** @var FileItem $item */ 163 | foreach ($items as $item) { 164 | $ext = strtolower(pathinfo($item->get('internal_name'), PATHINFO_EXTENSION)); 165 | 166 | $listItem = array( 167 | 'id' => $item->get('id'), 168 | 'name' => $item->get('name'), 169 | 'ext' => $ext, 170 | 'type' => 'file', 171 | 'size' => $item->getSize(), 172 | 'thumb' => $thumb, 173 | 'leaf' => true, 174 | 'perms' => '', 175 | 'thumb_width' => $thumbWidth, 176 | 'thumb_height' => $thumbHeight, 177 | 'disabled' => false 178 | ); 179 | 180 | if (in_array($ext, $imagesExts)) { 181 | /* get thumbnail */ 182 | $preview = 1; 183 | 184 | /* generate thumb/image URLs */ 185 | $thumbQuery = http_build_query(array( 186 | 'src' => $item->getPath(), 187 | 'w' => $thumbWidth, 188 | 'h' => $thumbHeight, 189 | 'f' => $thumbnailType, 190 | 'q' => $thumbnailQuality, 191 | 'far' => 'C', 192 | 'HTTP_MODAUTH' => $modAuth, 193 | 'wctx' => $this->xpdo->context->get('key'), 194 | 'source' => $this->parentSourceID 195 | )); 196 | 197 | $imageQuery = http_build_query(array( 198 | 'src' => $item->getPath(), 199 | 'w' => $imageWidth, 200 | 'h' => $imageHeight, 201 | 'f' => $thumbnailType, 202 | 'q' => $thumbnailQuality, 203 | 'far' => 'C', 204 | 'HTTP_MODAUTH' => $modAuth, 205 | 'wctx' => $this->xpdo->context->get('key'), 206 | 'source' => $this->parentSourceID 207 | )); 208 | 209 | $thumb = $thumbUrl . urldecode($thumbQuery); 210 | 211 | $listItem['image'] = $thumbUrl . urldecode($imageQuery); 212 | } else { 213 | $preview = 0; 214 | $thumb = $thumb_default; 215 | $listItem['image'] = $thumb; 216 | } 217 | 218 | $listItem['thumb'] = $thumb; 219 | $listItem['preview'] = $preview; 220 | 221 | $list[] = $listItem; 222 | } 223 | } 224 | 225 | return $list; 226 | } 227 | 228 | 229 | /** 230 | * Get the default properties for the filesystem media source type. 231 | * 232 | * @return array 233 | */ 234 | public function getDefaultProperties() { 235 | return array( 236 | 'imageExtensions' => array( 237 | 'name' => 'imageExtensions', 238 | 'desc' => 'prop_file.imageExtensions_desc', 239 | 'type' => 'textfield', 240 | 'value' => 'jpg,jpeg,png,gif', 241 | 'lexicon' => 'core:source', 242 | ), 243 | 'thumbnailType' => array( 244 | 'name' => 'thumbnailType', 245 | 'desc' => 'prop_file.thumbnailType_desc', 246 | 'type' => 'list', 247 | 'options' => array( 248 | array('name' => 'PNG','value' => 'png'), 249 | array('name' => 'JPG','value' => 'jpg'), 250 | array('name' => 'GIF','value' => 'gif'), 251 | ), 252 | 'value' => 'png', 253 | 'lexicon' => 'core:source', 254 | ), 255 | 'thumbnailQuality' => array( 256 | 'name' => 'thumbnailQuality', 257 | 'desc' => 'prop_file.thumbnailQuality_desc', 258 | 'type' => 'textfield', 259 | 'options' => '', 260 | 'value' => 90, 261 | 'lexicon' => 'core:source', 262 | ) 263 | ); 264 | } 265 | 266 | 267 | /** 268 | * Prepare the source path for phpThumb 269 | * 270 | * @param string $src 271 | * @return string 272 | */ 273 | public function prepareSrcForThumb($value) { 274 | return $this->getObjectUrl($value); 275 | } 276 | 277 | 278 | /** 279 | * Get the name of this source type 280 | * @return string 281 | */ 282 | public function getTypeName() { 283 | $this->xpdo->lexicon->load('fileattach:source'); 284 | return $this->xpdo->lexicon('fileattach.source_name'); 285 | } 286 | 287 | 288 | /** 289 | * Get the description of this source type 290 | * @return string 291 | */ 292 | public function getTypeDescription() { 293 | $this->xpdo->lexicon->load('fileattach:source'); 294 | return $this->xpdo->lexicon('fileattach.source_desc'); 295 | } 296 | } -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/fileitem.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | class FileItem extends xPDOSimpleObject { 26 | public $source = false; 27 | public $files_path = ''; 28 | 29 | 30 | /** 31 | * Creates a FileItem instance 32 | * 33 | * {@inheritdoc} 34 | */ 35 | function __construct(& $xpdo) { 36 | parent :: __construct($xpdo); 37 | 38 | $this->files_path = $this->xpdo->getOption('fileattach.files_path'); 39 | } 40 | 41 | 42 | /** 43 | * Get the source, preparing it for usage. 44 | * 45 | * @return source 46 | */ 47 | private function getMediaSource() { 48 | if ($this->source) 49 | return $this->source; 50 | 51 | //get modMediaSource 52 | $mediaSource = $this->xpdo->getOption('fileattach.mediasource', null, 1); 53 | 54 | $def = $this->xpdo->getObject('sources.modMediaSource', array('id' => $mediaSource)); 55 | $def->initialize(); 56 | $this->source = $def; 57 | 58 | return $this->source; 59 | } 60 | 61 | 62 | /** 63 | * Get object URL 64 | * 65 | * @return string 66 | */ 67 | function getUrl() { 68 | $ms = $this->getMediaSource(); 69 | return $ms->getBaseUrl() . $this->getPath(); 70 | } 71 | 72 | 73 | /** 74 | * Get relative file path 75 | * 76 | * @return string 77 | */ 78 | function getPath() { 79 | return $this->files_path . $this->get('path') . $this->get('internal_name'); 80 | } 81 | 82 | 83 | /** 84 | * Get full file path in fs 85 | * 86 | * @return string 87 | */ 88 | function getFullPath() { 89 | $ms = $this->getMediaSource(); 90 | return $ms->getBasePath() . $this->getPath(); 91 | } 92 | 93 | 94 | /** 95 | * Get file size 96 | * 97 | * @return int 98 | */ 99 | function getSize() { 100 | $ms = $this->getMediaSource(); 101 | $f = $ms->fileHandler->make($this->getFullPath(), array(), 'modFile'); 102 | return $f->getSize(); 103 | } 104 | 105 | 106 | /** 107 | * Rename file 108 | * 109 | * @param string $newname 110 | * @return boolean 111 | */ 112 | function rename($newname) { 113 | $local_path = $this->files_path . $this->get('path'); 114 | 115 | $ms = $this->getMediaSource(); 116 | 117 | if ($ms->renameObject($local_path . $this->get('internal_name'), $newname)) { 118 | $this->set('name', $newname); 119 | $this->set('internal_name', $newname); 120 | } else 121 | return false; 122 | 123 | return true; 124 | } 125 | 126 | 127 | /** 128 | * Set privacy mode 129 | * 130 | * @param boolean $state 131 | * @return boolean 132 | */ 133 | function setPrivate($state) { 134 | if ($this->get('private') == $state) 135 | return true; 136 | 137 | $ms = $this->getMediaSource(); 138 | 139 | $local_path = $this->files_path . $this->get('path'); 140 | $path = $ms->getBasePath() . $local_path; 141 | 142 | $ext = pathinfo($this->get('name'), PATHINFO_EXTENSION); 143 | $ext = strtolower($ext); 144 | 145 | // Generate name and check for existence 146 | if ($state) 147 | $filename = $this->generateName() . ".$ext"; 148 | else 149 | $filename = $this->get('name'); 150 | 151 | $fullpath = ''; 152 | 153 | // Check intersection with existing 154 | while(1) { 155 | $f = $ms->fileHandler->make($path . '/' . $filename, array(), 'modFile'); 156 | if (!$f->exists()) break; 157 | 158 | // Generate new name again 159 | if ($state) 160 | $filename = $this->generateName() . ".$ext"; 161 | else 162 | $filename = $this->generateName(4) . '_' . $filename; 163 | } 164 | 165 | if ($ms->renameObject( 166 | $local_path . $this->get('internal_name'), 167 | $filename)) { 168 | $this->set('internal_name', $filename); 169 | $this->set('private', $state); 170 | $this->save(); 171 | 172 | return true; 173 | } else 174 | $this->xpdo->log(xPDO::LOG_LEVEL_ERROR,'[FileAttach] An error occurred while trying to rename the attachment file at: ' . $filename); 175 | 176 | return false; 177 | } 178 | 179 | 180 | /** 181 | * Remove file 182 | */ 183 | function removeFile() { 184 | $filename = $this->getPath(); 185 | 186 | if (!empty($filename)) { 187 | $ms = $this->getMediaSource(); 188 | if (!@$ms->removeObject($filename)) 189 | $this->xpdo->log(xPDO::LOG_LEVEL_ERROR,'[FileAttach] An error occurred while trying to remove the attachment file at: ' . $filename); 190 | } 191 | } 192 | 193 | 194 | /** 195 | * Remove file and object 196 | * 197 | * @param array $ancestors 198 | */ 199 | function remove(array $ancestors= array ()) { 200 | $this->removeFile(); 201 | 202 | $this->xpdo->invokeEvent('faOnRemove', array( 203 | 'id' => $this->get('id'), 204 | 'object' => &$this) 205 | ); 206 | 207 | return parent::remove($ancestors); 208 | } 209 | 210 | 211 | /* Generate Filename 212 | * 213 | * @param integer $length Length of generated sequence 214 | * @return string 215 | */ 216 | static function generateName($length = 32) { 217 | $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'; 218 | $charactersLength = strlen($characters); 219 | 220 | $newname = ''; 221 | 222 | for ($i = 0; $i < $length; $i++) 223 | $newname .= $characters[rand(0, $charactersLength - 1)]; 224 | 225 | return $newname; 226 | } 227 | 228 | 229 | /* Sanitize Filename 230 | * 231 | * @param string $str Input file name 232 | * @return string 233 | */ 234 | static function sanitizeName($str) { 235 | $bad = array( 236 | '../', '', '<', '>', 237 | "'", '"', '&', '$', '#', 238 | '{', '}', '[', ']', '=', 239 | ';', '?', '%20', '%22', 240 | '%3c', // < 241 | '%253c', // < 242 | '%3e', // > 243 | '%0e', // > 244 | '%28', // ( 245 | '%29', // ) 246 | '%2528', // ( 247 | '%26', // & 248 | '%24', // $ 249 | '%3f', // ? 250 | '%3b', // ; 251 | '%3d', // = 252 | '/', './', '\\' 253 | ); 254 | 255 | return stripslashes(str_replace($bad, '', $str)); 256 | } 257 | } -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/metadata.mysql.php: -------------------------------------------------------------------------------- 1 | 5 | array ( 6 | 0 => 'FileItem', 7 | ), 8 | 'modMediaSource' => 9 | array ( 10 | 0 => 'FileAttachMediaSource', 11 | ), 12 | ); -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/metadata.sqlsrv.php: -------------------------------------------------------------------------------- 1 | 5 | array ( 6 | 0 => 'FileItem', 7 | ), 8 | 'modMediaSource' => 9 | array ( 10 | 0 => 'FileAttachMediaSource', 11 | ), 12 | ); -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/mysql/fileattachmediasource.class.php: -------------------------------------------------------------------------------- 1 | 'fileattach', 4 | 'version' => '1.1', 5 | 'extends' => 'modMediaSource', 6 | 'tableMeta' => 7 | array ( 8 | 'engine' => 'MyISAM', 9 | ), 10 | 'fields' => 11 | array ( 12 | ), 13 | 'fieldMeta' => 14 | array ( 15 | ), 16 | ); 17 | -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/mysql/fileitem.class.php: -------------------------------------------------------------------------------- 1 | 'fileattach', 4 | 'version' => '1.1', 5 | 'table' => 'files', 6 | 'extends' => 'xPDOSimpleObject', 7 | 'tableMeta' => 8 | array ( 9 | 'engine' => 'MyISAM', 10 | ), 11 | 'fields' => 12 | array ( 13 | 'fid' => '', 14 | 'name' => '', 15 | 'internal_name' => '', 16 | 'path' => '', 17 | 'description' => '', 18 | 'hash' => NULL, 19 | 'tag' => '', 20 | 'private' => 0, 21 | 'download' => 0, 22 | 'docid' => 0, 23 | 'uid' => 0, 24 | 'rank' => 0, 25 | ), 26 | 'fieldMeta' => 27 | array ( 28 | 'fid' => 29 | array ( 30 | 'dbtype' => 'varchar', 31 | 'precision' => '40', 32 | 'phptype' => 'string', 33 | 'null' => false, 34 | 'default' => '', 35 | ), 36 | 'name' => 37 | array ( 38 | 'dbtype' => 'varchar', 39 | 'precision' => '255', 40 | 'phptype' => 'string', 41 | 'null' => false, 42 | 'default' => '', 43 | ), 44 | 'internal_name' => 45 | array ( 46 | 'dbtype' => 'varchar', 47 | 'precision' => '255', 48 | 'phptype' => 'string', 49 | 'null' => false, 50 | 'default' => '', 51 | ), 52 | 'path' => 53 | array ( 54 | 'dbtype' => 'varchar', 55 | 'precision' => '100', 56 | 'phptype' => 'string', 57 | 'null' => false, 58 | 'default' => '', 59 | ), 60 | 'description' => 61 | array ( 62 | 'dbtype' => 'varchar', 63 | 'precision' => '255', 64 | 'phptype' => 'string', 65 | 'null' => false, 66 | 'default' => '', 67 | ), 68 | 'hash' => 69 | array ( 70 | 'dbtype' => 'varchar', 71 | 'precision' => '50', 72 | 'phptype' => 'string', 73 | 'null' => true, 74 | ), 75 | 'tag' => 76 | array ( 77 | 'dbtype' => 'varchar', 78 | 'precision' => '50', 79 | 'phptype' => 'string', 80 | 'null' => false, 81 | 'default' => '', 82 | ), 83 | 'private' => 84 | array ( 85 | 'dbtype' => 'tinyint', 86 | 'precision' => '1', 87 | 'phptype' => 'boolean', 88 | 'attributes' => 'unsigned', 89 | 'null' => false, 90 | 'default' => 0, 91 | ), 92 | 'download' => 93 | array ( 94 | 'dbtype' => 'int', 95 | 'precision' => '10', 96 | 'phptype' => 'integer', 97 | 'attributes' => 'unsigned', 98 | 'null' => false, 99 | 'default' => 0, 100 | ), 101 | 'docid' => 102 | array ( 103 | 'dbtype' => 'int', 104 | 'precision' => '10', 105 | 'phptype' => 'integer', 106 | 'null' => false, 107 | 'default' => 0, 108 | ), 109 | 'uid' => 110 | array ( 111 | 'dbtype' => 'int', 112 | 'precision' => '10', 113 | 'phptype' => 'integer', 114 | 'null' => false, 115 | 'default' => 0, 116 | ), 117 | 'rank' => 118 | array ( 119 | 'dbtype' => 'int', 120 | 'precision' => '10', 121 | 'phptype' => 'integer', 122 | 'attributes' => 'unsigned', 123 | 'null' => false, 124 | 'default' => 0, 125 | ), 126 | ), 127 | 'indexes' => 128 | array ( 129 | 'fid' => 130 | array ( 131 | 'alias' => 'fid', 132 | 'primary' => false, 133 | 'unique' => false, 134 | 'type' => 'BTREE', 135 | 'columns' => 136 | array ( 137 | 'fid' => 138 | array ( 139 | 'length' => '', 140 | 'collation' => 'A', 141 | 'null' => false, 142 | ), 143 | ), 144 | ), 145 | 'name' => 146 | array ( 147 | 'alias' => 'name', 148 | 'primary' => false, 149 | 'unique' => false, 150 | 'type' => 'BTREE', 151 | 'columns' => 152 | array ( 153 | 'name' => 154 | array ( 155 | 'length' => '', 156 | 'collation' => 'A', 157 | 'null' => false, 158 | ), 159 | ), 160 | ), 161 | 'docid' => 162 | array ( 163 | 'alias' => 'docid', 164 | 'primary' => false, 165 | 'unique' => false, 166 | 'type' => 'BTREE', 167 | 'columns' => 168 | array ( 169 | 'docid' => 170 | array ( 171 | 'length' => '', 172 | 'collation' => 'A', 173 | 'null' => false, 174 | ), 175 | ), 176 | ), 177 | 'uid' => 178 | array ( 179 | 'alias' => 'uid', 180 | 'primary' => false, 181 | 'unique' => false, 182 | 'type' => 'BTREE', 183 | 'columns' => 184 | array ( 185 | 'uid' => 186 | array ( 187 | 'length' => '', 188 | 'collation' => 'A', 189 | 'null' => false, 190 | ), 191 | ), 192 | ), 193 | ), 194 | 'aggregates' => 195 | array ( 196 | 'Document' => 197 | array ( 198 | 'class' => 'modResource', 199 | 'local' => 'docid', 200 | 'foreign' => 'id', 201 | 'cardinality' => 'one', 202 | 'owner' => 'foreign', 203 | ), 204 | ), 205 | ); 206 | -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/sqlsrv/fileattachmediasource.class.php: -------------------------------------------------------------------------------- 1 | 'fileattach', 4 | 'version' => '1.1', 5 | 'extends' => 'modMediaSource', 6 | 'fields' => 7 | array ( 8 | ), 9 | 'fieldMeta' => 10 | array ( 11 | ), 12 | ); 13 | -------------------------------------------------------------------------------- /core/components/fileattach/model/fileattach/sqlsrv/fileitem.class.php: -------------------------------------------------------------------------------- 1 | 'fileattach', 4 | 'version' => '1.1', 5 | 'table' => 'files', 6 | 'extends' => 'xPDOSimpleObject', 7 | 'fields' => 8 | array ( 9 | 'fid' => '', 10 | 'name' => '', 11 | 'internal_name' => '', 12 | 'path' => '', 13 | 'description' => '', 14 | 'hash' => NULL, 15 | 'tag' => '', 16 | 'private' => 0, 17 | 'download' => 0, 18 | 'docid' => 0, 19 | 'uid' => 0, 20 | 'rank' => 0, 21 | ), 22 | 'fieldMeta' => 23 | array ( 24 | 'fid' => 25 | array ( 26 | 'dbtype' => 'nvarchar', 27 | 'precision' => '40', 28 | 'phptype' => 'string', 29 | 'null' => false, 30 | 'default' => '', 31 | ), 32 | 'name' => 33 | array ( 34 | 'dbtype' => 'nvarchar', 35 | 'precision' => '255', 36 | 'phptype' => 'string', 37 | 'null' => false, 38 | 'default' => '', 39 | ), 40 | 'internal_name' => 41 | array ( 42 | 'dbtype' => 'nvarchar', 43 | 'precision' => '255', 44 | 'phptype' => 'string', 45 | 'null' => false, 46 | 'default' => '', 47 | ), 48 | 'path' => 49 | array ( 50 | 'dbtype' => 'nvarchar', 51 | 'precision' => '100', 52 | 'phptype' => 'string', 53 | 'null' => false, 54 | 'default' => '', 55 | ), 56 | 'description' => 57 | array ( 58 | 'dbtype' => 'nvarchar', 59 | 'precision' => '255', 60 | 'phptype' => 'string', 61 | 'null' => false, 62 | 'default' => '', 63 | ), 64 | 'hash' => 65 | array ( 66 | 'dbtype' => 'nvarchar', 67 | 'precision' => '50', 68 | 'phptype' => 'string', 69 | 'null' => true, 70 | ), 71 | 'tag' => 72 | array ( 73 | 'dbtype' => 'nvarchar', 74 | 'precision' => '50', 75 | 'phptype' => 'string', 76 | 'null' => false, 77 | 'default' => '', 78 | ), 79 | 'private' => 80 | array ( 81 | 'dbtype' => 'bit', 82 | 'phptype' => 'boolean', 83 | 'null' => false, 84 | 'default' => 0, 85 | ), 86 | 'download' => 87 | array ( 88 | 'dbtype' => 'int', 89 | 'precision' => '10', 90 | 'phptype' => 'integer', 91 | 'attributes' => 'unsigned', 92 | 'null' => false, 93 | 'default' => 0, 94 | ), 95 | 'docid' => 96 | array ( 97 | 'dbtype' => 'int', 98 | 'precision' => '10', 99 | 'phptype' => 'integer', 100 | 'null' => false, 101 | 'default' => 0, 102 | ), 103 | 'uid' => 104 | array ( 105 | 'dbtype' => 'int', 106 | 'precision' => '10', 107 | 'phptype' => 'integer', 108 | 'null' => false, 109 | 'default' => 0, 110 | ), 111 | 'rank' => 112 | array ( 113 | 'dbtype' => 'int', 114 | 'precision' => '10', 115 | 'phptype' => 'integer', 116 | 'attributes' => 'unsigned', 117 | 'null' => false, 118 | 'default' => 0, 119 | ), 120 | ), 121 | 'indexes' => 122 | array ( 123 | 'fid' => 124 | array ( 125 | 'alias' => 'fid', 126 | 'primary' => false, 127 | 'unique' => false, 128 | 'type' => 'BTREE', 129 | 'columns' => 130 | array ( 131 | 'fid' => 132 | array ( 133 | 'length' => '', 134 | 'collation' => 'A', 135 | 'null' => false, 136 | ), 137 | ), 138 | ), 139 | 'name' => 140 | array ( 141 | 'alias' => 'name', 142 | 'primary' => false, 143 | 'unique' => false, 144 | 'type' => 'BTREE', 145 | 'columns' => 146 | array ( 147 | 'name' => 148 | array ( 149 | 'length' => '', 150 | 'collation' => 'A', 151 | 'null' => false, 152 | ), 153 | ), 154 | ), 155 | 'docid' => 156 | array ( 157 | 'alias' => 'docid', 158 | 'primary' => false, 159 | 'unique' => false, 160 | 'type' => 'BTREE', 161 | 'columns' => 162 | array ( 163 | 'docid' => 164 | array ( 165 | 'length' => '', 166 | 'collation' => 'A', 167 | 'null' => false, 168 | ), 169 | ), 170 | ), 171 | 'uid' => 172 | array ( 173 | 'alias' => 'uid', 174 | 'primary' => false, 175 | 'unique' => false, 176 | 'type' => 'BTREE', 177 | 'columns' => 178 | array ( 179 | 'uid' => 180 | array ( 181 | 'length' => '', 182 | 'collation' => 'A', 183 | 'null' => false, 184 | ), 185 | ), 186 | ), 187 | ), 188 | 'aggregates' => 189 | array ( 190 | 'Document' => 191 | array ( 192 | 'class' => 'modResource', 193 | 'local' => 'docid', 194 | 'foreign' => 'id', 195 | 'cardinality' => 'one', 196 | 'owner' => 'foreign', 197 | ), 198 | ), 199 | ); 200 | -------------------------------------------------------------------------------- /core/components/fileattach/model/schema/fileattach.mysql.schema.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /core/components/fileattach/model/schema/fileattach.sqlsrv.schema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/access.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Set private flag 27 | */ 28 | class FileItemAccessProcessor extends modObjectProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'save'; 33 | 34 | /** 35 | * @return array|string 36 | */ 37 | public function process() { 38 | if (!$this->checkPermissions()) 39 | return $this->failure($this->modx->lexicon('access_denied')); 40 | 41 | $private = ($this->getProperty('private'))? true : false; 42 | $ids = $this->modx->fromJSON($this->getProperty('ids')); 43 | 44 | if (empty($ids)) 45 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 46 | 47 | foreach ($ids as $id) { 48 | /** @var FileItemItem $object */ 49 | if (!$object = $this->modx->getObject($this->classKey, $id)) 50 | return $this->failure($this->modx->lexicon('fileattach.item_err_nf')); 51 | 52 | if (!$object->setPrivate($private)) 53 | return $this->failure($this->modx->lexicon('fileattach.item_err_nr')); 54 | } 55 | 56 | return $this->success(); 57 | } 58 | } 59 | 60 | return 'FileItemAccessProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/create.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Create an Item 27 | */ 28 | class FileItemCreateProcessor extends modObjectCreateProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'create'; 33 | 34 | /** 35 | * @return bool 36 | */ 37 | public function beforeSet() { 38 | $docid = (int) $this->getProperty('docid'); 39 | 40 | if (!$docid) 41 | $this->modx->error->addField('docid', $this->modx->lexicon('notset')); 42 | 43 | $name = trim($this->getProperty('name')); 44 | $name = $this->object->sanitizeName($name); 45 | $this->setProperty('name', $name); 46 | 47 | $this->setProperty('fid', $this->object->generateName()); 48 | 49 | if (empty($name)) 50 | $this->modx->error->addField('name', $this->modx->lexicon('fileattach.item_err_name')); 51 | 52 | return parent::beforeSet(); 53 | } 54 | } 55 | 56 | return 'FileItemCreateProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/get.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Get an Item 27 | */ 28 | class FileItemGetProcessor extends modObjectGetProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach:default'); 32 | public $permission = 'view'; 33 | 34 | 35 | /** 36 | * We doing special check of permission 37 | * because of our objects is not an instances of modAccessibleObject 38 | * 39 | * @return mixed 40 | */ 41 | public function process() { 42 | if (!$this->checkPermissions()) 43 | return $this->failure($this->modx->lexicon('access_denied')); 44 | 45 | return parent::process(); 46 | } 47 | 48 | } 49 | 50 | return 'FileItemGetProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/getlist.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Get a list of Items 27 | */ 28 | class FileItemGetListProcessor extends modObjectGetListProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $defaultSortField = 'id'; 32 | public $defaultSortDirection = 'DESC'; 33 | public $permission = 'list'; 34 | 35 | /** 36 | * * We doing special check of permission 37 | * because of our objects is not an instances of modAccessibleObject 38 | * 39 | * @return boolean|string 40 | */ 41 | public function beforeQuery() { 42 | if (!$this->checkPermissions()) 43 | return $this->modx->lexicon('access_denied'); 44 | 45 | return true; 46 | } 47 | 48 | 49 | /** 50 | * @param xPDOQuery $c 51 | * 52 | * @return xPDOQuery 53 | */ 54 | public function prepareQueryBeforeCount(xPDOQuery $c) { 55 | $docid = (int) $this->getProperty('docid'); 56 | $uid = trim($this->getProperty('uid')); 57 | $query = trim($this->getProperty('query')); 58 | 59 | $c->select($this->modx->getSelectColumns('FileItem', 'FileItem')); 60 | 61 | if ($query) 62 | $c->where(array('name:LIKE' => "%$query%")); 63 | 64 | if ($uid || ($docid == 0)) { 65 | $c->select('User.username'); 66 | $c->leftJoin('modUser', 'User', 'User.id=FileItem.uid'); 67 | } 68 | 69 | if ($uid) 70 | $c->where(array('User.username:LIKE' => "%$uid%")); 71 | 72 | if ($docid > 0) 73 | $c->where(array('docid' => $docid)); 74 | else { 75 | $c->select('Res.pagetitle'); 76 | $c->leftJoin('modResource', 'Res', 'Res.id=FileItem.docid'); 77 | } 78 | 79 | return $c; 80 | } 81 | } 82 | 83 | return 'FileItemGetListProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/hash.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Reset download counter 27 | */ 28 | class FileItemCalcHashProcessor extends modObjectGetProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'save'; 33 | 34 | public function cleanup() { 35 | $hash = sha1($this->object->getFullPath()); 36 | 37 | $this->object->set('hash', $hash); 38 | $this->object->save(); 39 | 40 | return $this->success('', array('hash' => $hash)); 41 | } 42 | } 43 | 44 | return 'FileItemCalcHashProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/rank.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Set rank 27 | */ 28 | class FileItemSetRankProcessor extends modObjectProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'save'; 33 | 34 | /** 35 | * @return array|string 36 | */ 37 | public function process() { 38 | if (!$this->checkPermissions()) 39 | return $this->failure($this->modx->lexicon('access_denied')); 40 | 41 | $ranklist = $this->modx->fromJSON($this->getProperty('rank')); 42 | 43 | if (empty($ranklist)) 44 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 45 | 46 | foreach ($ranklist as $id => $value) { 47 | /** @var FileItemItem $object */ 48 | if (!$object = $this->modx->getObject($this->classKey, $id)) 49 | return $this->failure($this->modx->lexicon('fileattach.item_err_nf')); 50 | 51 | $object->set('rank', $value); 52 | $object->save(); 53 | } 54 | 55 | return $this->success(); 56 | } 57 | } 58 | 59 | return 'FileItemSetRankProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/remove.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Remove an Items 27 | */ 28 | class FileItemRemoveProcessor extends modObjectProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('File'); 32 | public $permission = 'remove'; 33 | 34 | 35 | /** 36 | * @return array|string 37 | */ 38 | public function process() { 39 | if (!$this->checkPermissions()) 40 | return $this->failure($this->modx->lexicon('access_denied')); 41 | 42 | $ids = $this->modx->fromJSON($this->getProperty('ids')); 43 | if (empty($ids)) 44 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 45 | 46 | foreach ($ids as $id) { 47 | /** @var FileItem $object */ 48 | if (!$object = $this->modx->getObject($this->classKey, $id)) 49 | return $this->failure($this->modx->lexicon('fileattach.item_err_nf')); 50 | 51 | $object->remove(); 52 | } 53 | 54 | return $this->success(); 55 | } 56 | } 57 | 58 | return 'FileItemRemoveProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/reset.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Reset download counter 27 | */ 28 | class FileItemResetProcessor extends modObjectProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'save'; 33 | 34 | /** 35 | * @return array|string 36 | */ 37 | public function process() { 38 | if (!$this->checkPermissions()) 39 | return $this->failure($this->modx->lexicon('access_denied')); 40 | 41 | $ids = $this->modx->fromJSON($this->getProperty('ids')); 42 | 43 | if (empty($ids)) 44 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 45 | 46 | foreach ($ids as $id) { 47 | /** @var FileItemItem $object */ 48 | if (!$object = $this->modx->getObject($this->classKey, $id)) 49 | return $this->failure($this->modx->lexicon('fileattach.item_err_nf')); 50 | 51 | $object->set('download', 0); 52 | $object->save(); 53 | } 54 | 55 | return $this->success(); 56 | } 57 | } 58 | 59 | return 'FileItemResetProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/searchres.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Searches for specific resources and returns them in an array. 27 | * 28 | * @param integer $start The page to start on 29 | * @param integer $limit (optional) The number of results to limit by 30 | * @param string $sort The column to sort by 31 | * @param string $dir The direction to sort 32 | * @return array An array of modResources 33 | * 34 | * @package modx 35 | * @subpackage processors.resource 36 | */ 37 | class modFileItemSearchResourceProcessor extends modObjectGetListProcessor { 38 | public $classKey = 'modResource'; 39 | public $languageTopics = array('resource'); 40 | public $permission = 'search'; 41 | public $defaultSortField = 'pagetitle'; 42 | 43 | /** @var array $contextKeys */ 44 | public $contextKeys = array(); 45 | /** @var array $actions */ 46 | public $actions = array(); 47 | /** @var string $charset */ 48 | public $charset = 'UTF-8'; 49 | 50 | public function beforeQuery() { 51 | $this->contextKeys = $this->getContextKeys(); 52 | if (empty($this->contextKeys)) 53 | return $this->modx->lexicon('permission_denied'); 54 | 55 | return true; 56 | } 57 | 58 | public function prepareQueryBeforeCount(xPDOQuery $c) { 59 | $id = $this->getProperty('id'); 60 | $query = $this->getProperty('query'); 61 | $templates = $this->modx->getOption('fileattach.templates'); 62 | 63 | $where = array('context_key:IN' => $this->contextKeys); 64 | 65 | if ($templates != '') 66 | $where['template:IN'] = explode(',', $templates); 67 | 68 | if (!empty($id)) $where['id'] = $id; 69 | if (!empty($query)) $where['pagetitle:LIKE'] = "%$query%"; 70 | 71 | $c->select('id,pagetitle,description'); 72 | $c->where($where); 73 | 74 | return $c; 75 | } 76 | 77 | /** 78 | * Get a collection of Context keys that the User can access for all the Resources 79 | * @return array 80 | */ 81 | public function getContextKeys() { 82 | $contextKeys = array(); 83 | $contexts = $this->modx->getCollection('modContext', array('key:!=' => 'mgr')); 84 | 85 | /** @var modContext $context */ 86 | foreach ($contexts as $context) { 87 | if ($context->checkPolicy('list')) 88 | $contextKeys[] = $context->get('key'); 89 | } 90 | 91 | return $contextKeys; 92 | } 93 | 94 | public function beforeIteration(array $list) { 95 | $this->charset = $this->modx->getOption('modx_charset',null,'UTF-8'); 96 | return $list; 97 | } 98 | 99 | public function prepareRow(xPDOObject $object) { 100 | $objectArray = $object->toArray(); 101 | 102 | $objectArray['pagetitle'] = htmlentities($objectArray['pagetitle'],ENT_COMPAT,$this->charset); 103 | $objectArray['description'] = htmlentities($objectArray['description'],ENT_COMPAT,$this->charset); 104 | 105 | return array( 106 | 'id' => $objectArray['id'], 107 | 'pagetitle' => $objectArray['pagetitle'], 108 | 'description' => $objectArray['description'], 109 | ); 110 | } 111 | } 112 | 113 | return 'modFileItemSearchResourceProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/update.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Update an Item 27 | */ 28 | class FileItemUpdateProcessor extends modObjectUpdateProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('fileattach'); 32 | public $permission = 'save'; 33 | 34 | 35 | /** 36 | * We doing special check of permission 37 | * because of our objects is not an instances of modAccessibleObject 38 | * 39 | * @return bool|string 40 | */ 41 | public function beforeSave() { 42 | if (!$this->checkPermissions()) 43 | return $this->modx->lexicon('access_denied'); 44 | 45 | return true; 46 | } 47 | 48 | 49 | /** 50 | * @return bool 51 | */ 52 | public function beforeSet() { 53 | $id = (int)$this->getProperty('id'); 54 | $docid = (int)$this->getProperty('docid'); 55 | 56 | if (empty($id)) 57 | return $this->modx->lexicon('fileattach.item_err_ns'); 58 | 59 | if (!$docid) 60 | $this->modx->error->addField('docid', $this->modx->lexicon('notset')); 61 | 62 | $private = ($this->getProperty('private'))? true : false; 63 | 64 | // Allow filename change only in private mode. May be changed further 65 | $name = trim($this->getProperty('name')); 66 | $name = $this->object->sanitizeName($name); 67 | if (empty($name)) 68 | $this->modx->error->addField('name', $this->modx->lexicon('fileattach.item_err_name')); 69 | 70 | // If file is open we should rename file, otherwize just change field value 71 | if (!$this->object->get('private')) { 72 | $this->unsetProperty('name'); 73 | 74 | // Rename if name changed 75 | if ($name != $this->object->get('name')) 76 | if (!$this->object->rename($name)) 77 | $this->modx->error->addField('name', $this->modx->lexicon('fileattach.item_err_nr')); 78 | } 79 | 80 | if (!$this->object->setPrivate($private)) 81 | $this->modx->error->addField('name', $this->modx->lexicon('fileattach.item_err_nr')); 82 | 83 | return parent::beforeSet(); 84 | } 85 | } 86 | 87 | return 'FileItemUpdateProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/mgr/upload.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Upload files to a directory 27 | * 28 | * @param string $docid resource ID 29 | */ 30 | class modFileAttachUploadProcessor extends modProcessor { 31 | /** @var modMediaSource $source */ 32 | private $source; 33 | private $privatemode; 34 | private $filename; 35 | public $path; 36 | private $localpath; 37 | 38 | private $calc_hash; 39 | private $user_folders; 40 | private $doc_folders; 41 | 42 | public function checkPermissions() { 43 | return $this->modx->hasPermission('file_upload'); 44 | } 45 | 46 | public function getLanguageTopics() { 47 | return array('file'); 48 | } 49 | 50 | public function initialize() { 51 | $this->calc_hash = $this->modx->getOption('fileattach.calchash'); 52 | $this->user_folders = $this->modx->getOption('fileattach.user_folders'); 53 | $this->doc_folders = $this->modx->getOption('fileattach.put_docid'); 54 | $this->path = $this->modx->getOption('fileattach.files_path'); 55 | $this->privatemode = $this->modx->getOption('fileattach.private'); 56 | $this->translit = $this->modx->getOption('fileattach.translit'); 57 | 58 | $this->setDefaultProperties(array('docid' => 0)); 59 | 60 | $this->localpath = ''; 61 | 62 | if ($this->user_folders) 63 | $this->localpath .= (int) $this->modx->user->get('id') . '/'; 64 | 65 | if ($this->doc_folders) 66 | $this->localpath .= (int) $this->getProperty('docid') . '/'; 67 | 68 | $this->setProperty('path', $this->path . $this->localpath); 69 | $this->setProperty('source', $this->modx->getOption('fileattach.mediasource')); 70 | 71 | if (!$this->getProperty('path')) return $this->modx->lexicon('file_folder_err_ns'); 72 | 73 | return true; 74 | } 75 | 76 | public function process() { 77 | if (!$this->getSource()) 78 | return $this->failure($this->modx->lexicon('permission_denied')); 79 | 80 | $this->source->setRequestProperties($this->getProperties()); 81 | $this->source->initialize(); 82 | 83 | if (!$this->source->checkPolicy('create')) 84 | return $this->failure($this->modx->lexicon('permission_denied')); 85 | 86 | // Create subfolder 87 | if ($this->user_folders || $this->doc_folders) { 88 | $path = $this->source->getBasePath() . $this->getProperty('path'); 89 | $d = $this->source->fileHandler->make($path, array(), 'modDirectory'); 90 | 91 | if (!$d->exists()) { 92 | if (!$this->source->createContainer($this->getProperty('path'), '')) 93 | return $this->failure($this->modx->lexicon('permission_denied')); 94 | } 95 | } 96 | 97 | $path = $this->source->getBasePath() . $this->getProperty('path'); 98 | $list = array(); 99 | 100 | $this->modx->loadClass('FileItem'); 101 | 102 | // Create serie of FileItem objects 103 | foreach ($_FILES as $file) { 104 | $filename = $file['name']; 105 | $ext = pathinfo($filename, PATHINFO_EXTENSION); 106 | $ext = strtolower($ext); 107 | 108 | if ($this->translit) 109 | $filename = modResource::filterPathSegment($this->modx, $filename); 110 | 111 | // Generate name and check for existence 112 | if ($this->privatemode) 113 | $this->filename = FileItem::generateName() . ".$ext"; 114 | else 115 | $this->filename = $filename; 116 | 117 | $fullpath = ''; 118 | 119 | while(1) { 120 | $fullpath = $path . '/' . $this->filename; 121 | $f = $this->source->fileHandler->make($fullpath, array(), 'modFile'); 122 | if (!$f->exists()) break; 123 | 124 | // Generate new name again 125 | if ($this->privatemode) 126 | $this->filename = FileItem::generateName() . ".$ext"; 127 | else 128 | $this->filename = '_' . $this->filename; 129 | } 130 | 131 | $success = $this->source->uploadObjectsToContainer( 132 | $this->getProperty('path'), 133 | array(array( // emulate a $_FILES object 134 | "name" => $this->filename, 135 | "tmp_name" => $file['tmp_name'], 136 | "error" => "0") 137 | )); 138 | 139 | if (empty($success)) { 140 | $msg = ''; 141 | $errors = $this->source->getErrors(); 142 | foreach ($errors as $k => $msg) { 143 | $this->modx->error->addField($k,$msg); 144 | } 145 | 146 | return $this->failure($msg); 147 | } else { 148 | $fid = FileItem::generateName(); 149 | $fileitem = $this->modx->newObject('FileItem', array( 150 | 'fid' => $fid, 151 | 'docid' => $this->getProperty('docid'), 152 | 'name' => $filename, 153 | 'internal_name' => $this->filename, 154 | 'path' => $this->localpath, 155 | 'private' => $this->privatemode, 156 | 'uid' => $this->modx->user->get('id'), 157 | 'hash' => ($this->calc_hash)? sha1_file($fullpath) : NULL 158 | )); 159 | 160 | if (!$fileitem->save()) 161 | return $this->failure($this->modx->lexicon('fileattach.item_err_save')); 162 | 163 | $list[] = array( 164 | 'id' => $fileitem->get('id'), 165 | 'fid' => $fid, 166 | 'name' => $filename); 167 | 168 | $this->modx->invokeEvent('faOnUploadItem', array( 169 | 'id' => $this->getProperty('docid'), 170 | 'object' => &$fileitem) 171 | ); 172 | } 173 | } 174 | 175 | $this->modx->invokeEvent('faOnUpload', array('id' => $this->getProperty('docid'))); 176 | 177 | return $this->outputArray($list, count($list)); 178 | } 179 | 180 | /** 181 | * Get the active Source 182 | * @return modMediaSource|boolean 183 | */ 184 | public function getSource() { 185 | if (empty($this->source)) { 186 | $this->modx->loadClass('sources.modMediaSource'); 187 | $this->source = modMediaSource::getDefaultSource($this->modx,$this->getProperty('source')); 188 | } 189 | 190 | if (empty($this->source) || !$this->source->getWorkingContext()) 191 | return false; 192 | 193 | return $this->source; 194 | } 195 | } 196 | 197 | return 'modFileAttachUploadProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/web/download.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | class FileItemDownloadProcessor extends modObjectProcessor { 26 | public $objectType = 'FileItem'; 27 | public $classKey = 'FileItem'; 28 | public $primaryKeyField = 'fid'; 29 | public $languageTopics = array('fileattach:default'); 30 | public $permission = 'fileattach.download'; 31 | private $primaryKey; 32 | 33 | /** 34 | * {@inheritDoc} 35 | * @return boolean 36 | */ 37 | public function initialize() { 38 | $this->primaryKey = $this->getProperty($this->primaryKeyField, false); 39 | if (empty($this->primaryKey)) 40 | return $this->modx->lexicon('fileattach.item_err_ns'); 41 | 42 | $this->object = $this->modx->getObject($this->classKey, array($this->primaryKeyField => $this->primaryKey)); 43 | if (empty($this->object)) 44 | return $this->modx->lexicon('fileattach.item_err_nfs', array($this->primaryKeyField => $this->primaryKey)); 45 | 46 | return parent::initialize(); 47 | } 48 | 49 | 50 | /* 51 | * {@inheritDoc} 52 | * @return redirect or bytestream 53 | */ 54 | public function process() { 55 | @session_write_close(); 56 | 57 | $perform_count = true; 58 | 59 | // If file is private then redirect else read file directly 60 | if ($this->object->get('private')) { 61 | // Get file info 62 | $filename = $this->object->getFullPath(); 63 | $filesize = filesize($filename); 64 | $mtime = filemtime($filename); 65 | 66 | if (isset($_SERVER['HTTP_RANGE'])) { 67 | // Get range 68 | $range = str_replace('bytes=', '', $_SERVER['HTTP_RANGE']); 69 | list($start, $end) = explode('-', $range); 70 | 71 | // Check data 72 | if (empty($start)) { 73 | header($_SERVER['SERVER_PROTOCOL'] . ' 416 Requested Range Not Satisfiable'); 74 | return; 75 | } else 76 | $perform_count = false; 77 | 78 | // Check range 79 | $start = intval($start); 80 | $end = intval($end); 81 | 82 | if (($end == 0) || ($end < $start) || ($end >= $filesize)) $end = $filesize - 1; 83 | 84 | $remain = $end - $start; 85 | 86 | if ($remain == 0) { 87 | header($_SERVER['SERVER_PROTOCOL'] . ' 416 Requested Range Not Satisfiable'); 88 | return; 89 | } 90 | 91 | header($_SERVER['SERVER_PROTOCOL'] . ' 206 Partial Content'); 92 | header("Content-Range: bytes $start-$end/$filesize"); 93 | } else { 94 | $remain = $filesize; 95 | } 96 | 97 | // Put headers 98 | $inline = (int) $this->getProperty('inline'); 99 | if (!$inline) { 100 | header('Content-Type: application/force-download'); 101 | header('Content-Disposition: attachment; filename="' . $this->object->get('name') . '"'); 102 | $perform_count = false; 103 | } 104 | 105 | header('Last-Modified: ' . gmdate('r', $mtime)); 106 | header('ETag: ' . sprintf('%x-%x-%x', fileinode($filename), $filesize, $mtime)); 107 | header('Accept-Ranges: bytes'); 108 | header('Content-Length: ' . $remain); 109 | header('Connection: close'); 110 | 111 | if ($range) { 112 | $fh = fopen($filename, 'rb'); 113 | fseek($fh, $start); 114 | 115 | // Output contents 116 | $blocksize = 8192; 117 | 118 | while (!feof($fh) && ($remain > 0)) { 119 | echo fread($fh, ($remain > $blocksize)? $blocksize : $remain); 120 | flush(); 121 | 122 | $remain -= $blocksize; 123 | } 124 | 125 | fclose($fh); 126 | } else { 127 | readfile($filename); 128 | } 129 | } else { 130 | // In public mode redirect to file url 131 | $fileurl = $this->object->getUrl(); 132 | header("Location: $fileurl", true, 302); 133 | } 134 | 135 | // Count downloads if allowed by config 136 | if ($perform_count && $this->modx->getOption('fileattach.download', null, true)) { 137 | $c = $this->modx->newQuery($this->classKey); 138 | $c->command('update'); 139 | $c->set(array( 140 | 'download' => $this->object->get('download') + 1 141 | )); 142 | $c->where(array( 143 | 'fid' => $this->primaryKey, 144 | )); 145 | $c->prepare(); 146 | $c->stmt->execute(); 147 | } 148 | } 149 | } 150 | 151 | return 'FileItemDownloadProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/web/getlist.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Get a list of Items 27 | */ 28 | class FileItemGetListProcessor extends modObjectGetListProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $defaultSortField = 'id'; 32 | public $defaultSortDirection = 'DESC'; 33 | public $permission = 'fileattach.list'; 34 | 35 | /** 36 | * * We doing special check of permission 37 | * because of our objects is not an instances of modAccessibleObject 38 | * 39 | * @return boolean|string 40 | */ 41 | public function beforeQuery() { 42 | if (!$this->checkPermissions()) 43 | return $this->modx->lexicon('access_denied'); 44 | 45 | $docid = (int) $this->getProperty('docid'); 46 | 47 | if (!$docid) 48 | return $this->modx->lexicon('fileattach.item_err_ns'); 49 | 50 | return true; 51 | } 52 | 53 | 54 | /** 55 | * @param xPDOQuery $c 56 | * 57 | * @return xPDOQuery 58 | */ 59 | public function prepareQueryBeforeCount(xPDOQuery $c) { 60 | $docid = (int) $this->getProperty('docid'); 61 | $query = trim($this->getProperty('query')); 62 | 63 | $c->select($this->modx->getSelectColumns('FileItem')); 64 | 65 | if ($query) 66 | $c->where(array('name:LIKE' => "%$query%")); 67 | 68 | $c->where(array('docid' => $docid)); 69 | 70 | return $c; 71 | } 72 | 73 | public function prepareRow(xPDOObject $object) { 74 | $resArray = array( 75 | 'id' => $object->get('id'), 76 | 'fid' => $object->get('fid'), 77 | 'name' => $object->get('name'), 78 | 'hash' => $object->get('hash') 79 | ); 80 | 81 | return $resArray; 82 | } 83 | } 84 | 85 | return 'FileItemGetListProcessor'; -------------------------------------------------------------------------------- /core/components/fileattach/processors/web/remove.class.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This file is part of FileAttach, tool to attach files to resources with 8 | * MODX Revolution's Manager. 9 | * 10 | * FileAttach is free software; you can redistribute it and/or modify it under the 11 | * terms of the GNU General Public License as published by the Free Software 12 | * Foundation version 3, 13 | * 14 | * FileAttach is distributed in the hope that it will be useful, but WITHOUT ANY 15 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 16 | * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License along with 19 | * FileAttach; if not, write to the Free Software Foundation, Inc., 59 Temple Place, 20 | * Suite 330, Boston, MA 02111-1307 USA 21 | * 22 | * @package FileAttach 23 | */ 24 | 25 | /** 26 | * Remove an Items 27 | */ 28 | class FileItemRemoveProcessor extends modObjectProcessor { 29 | public $objectType = 'FileItem'; 30 | public $classKey = 'FileItem'; 31 | public $languageTopics = array('File'); 32 | public $permission = 'fileattach.remove'; 33 | public $permission2 = 'fileattach.totallist'; 34 | 35 | 36 | /** 37 | * @return array|string 38 | */ 39 | public function process() { 40 | if (!$this->checkPermissions()) 41 | return $this->failure($this->modx->lexicon('access_denied')); 42 | 43 | $adminmode = $this->modx->hasPermission($this->permission2); 44 | 45 | $docid = (int) $this->getProperty('docid'); 46 | 47 | if (!$docid) 48 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 49 | 50 | $ids = $this->modx->fromJSON($this->getProperty('ids')); 51 | if (empty($ids)) 52 | return $this->failure($this->modx->lexicon('fileattach.item_err_ns')); 53 | 54 | foreach ($ids as $id) { 55 | /** @var FileItem $object */ 56 | if (!$object = $this->modx->getObject($this->classKey, $id)) 57 | return $this->failure($this->modx->lexicon('fileattach.item_err_nf')); 58 | 59 | // Forbid deletion for another resources 60 | if ($object->get('docid') != $docid) 61 | return $this->failure($this->modx->lexicon('fileattach.item_err_remove')); 62 | 63 | // Allow remove only for admins and file owners 64 | if ($adminmode || (($this->modx->user->get('id') == $object->get('uid')))) 65 | $object->remove(); 66 | else 67 | return $this->failure($this->modx->lexicon('fileattach.item_err_remove')); 68 | } 69 | 70 | return $this->success(); 71 | } 72 | } 73 | 74 | return 'FileItemRemoveProcessor'; --------------------------------------------------------------------------------