jdaehne / backupmodx Goto Github PK
View Code? Open in Web Editor NEWTiny Backup Widget for MODX-Sites
Tiny Backup Widget for MODX-Sites
Hey Jan,
We got some requests from clients who'd like to be able to do a quick 'Backup all content'. That would mean: modx_site_content + TV values. Is that something you might add to this extra?
A restore from backup would then also be possible.
Tested version: backupmodx-3.0.1-pl
On MODX 3 version: git install from 06/03/2021
Console running...
Attempting to install package with signature: backupmodx-3.0.1-pl
Package found...now preparing to install.
Grabbing package workspace...
Workspace environment initiated, now installing package...
modx.modNamespace is deprecated since version 3.0. Replace references to class modx.modNamespace with MODX\Revolution\modNamespace to take advantage of PSR-4 autoloading.
modNamespace is deprecated since version 3.0. Replace references to class modNamespace with MODX\Revolution\modNamespace to take advantage of PSR-4 autoloading.
modNamespace is deprecated since version 3.0. Replace references to class modNamespace with MODX\Revolution\modNamespace to take advantage of PSR-4 autoloading.
modx.modDashboardWidget is deprecated since version 3.0. Replace references to class modx.modDashboardWidget with MODX\Revolution\modDashboardWidget to take advantage of PSR-4 autoloading.
modDashboardWidget is deprecated since version 3.0. Replace references to class modDashboardWidget with MODX\Revolution\modDashboardWidget to take advantage of PSR-4 autoloading.
modDashboardWidget is deprecated since version 3.0. Replace references to class modDashboardWidget with MODX\Revolution\modDashboardWidget to take advantage of PSR-4 autoloading.
modx.modSystemSetting is deprecated since version 3.0. Replace references to class modx.modSystemSetting with MODX\Revolution\modSystemSetting to take advantage of PSR-4 autoloading.
modSystemSetting is deprecated since version 3.0. Replace references to class modSystemSetting with MODX\Revolution\modSystemSetting to take advantage of PSR-4 autoloading.
modSystemSetting is deprecated since version 3.0. Replace references to class modSystemSetting with MODX\Revolution\modSystemSetting to take advantage of PSR-4 autoloading.
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.debug )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.excludeFolders )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.excludeFiles )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.targetPath )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronKey )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronFiles )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronDatabase )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronNote )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronEnable )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronMaxDatabase )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.cronMaxFiles )
Skipping vehicle object of class modSystemSetting (data object exists and cannot be upgraded); criteria: Array ( [key] => backupmodx.groups )
modx.modCategory is deprecated since version 3.0. Replace references to class modx.modCategory with MODX\Revolution\modCategory to take advantage of PSR-4 autoloading.
modCategory is deprecated since version 3.0. Replace references to class modCategory with MODX\Revolution\modCategory to take advantage of PSR-4 autoloading.
modCategory is deprecated since version 3.0. Replace references to class modCategory with MODX\Revolution\modCategory to take advantage of PSR-4 autoloading.
Attempting to preserve files at /Users/bochkarev/Sites/bughunt/assets/components/backupmodx into archive /Users/bochkarev/Sites/bughunt/core/packages/backupmodx-3.0.1-pl/modCategory/b662f405b90ce3b175f6178490a46c50.0.preserved.zip
Attempting to preserve files at /Users/bochkarev/Sites/bughunt/core/components/backupmodx into archive /Users/bochkarev/Sites/bughunt/core/packages/backupmodx-3.0.1-pl/modCategory/b662f405b90ce3b175f6178490a46c50.1.preserved.zip
transport.modTransportPackage is deprecated since version 3.0. Replace references to class transport.modTransportPackage with MODX\Revolution\Transport\modTransportPackage to take advantage of PSR-4 autoloading.
Could not find legacy class modTransportPackage after converting to MODX\Revolution\modTransportPackage
Could not load class: modTransportPackage from mysql.modtransportpackage
Could not get table name for class:
transport.modTransportPackage is deprecated since version 3.0. Replace references to class transport.modTransportPackage with MODX\Revolution\Transport\modTransportPackage to take advantage of PSR-4 autoloading.
transport.modTransportPackage is deprecated since version 3.0. Replace references to class transport.modTransportPackage with MODX\Revolution\Transport\modTransportPackage to take advantage of PSR-4 autoloading.
Error 42000 executing statement: Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS `latestPackage` WHERE `latestPackage`.`package_name` = `modTransp' at line 3 )
Successfully installed package backupmodx-3.0.1-pl
Go to Settings -> Dashboards -> Edit Default. Click the Place Widget button, select BackupMODX from the list, click the Save button.
Click the Save button in the upper left corner and go to the main page of the control panel and get the error below.
Go through the different features it offers (i.e. different ways of using a snippet or settings)
TypeError: Argument 2 passed to modDashboardWidgetBackupModx::__construct() must be an instance of modDashboardWidget, object given, called in /Users/bochkarev/Sites/bughunt/core/src/Revolution/modDashboardWidget.php on line 90
Errors:
modDashboardWidgetBackupModx->__construct(object, object, object)
MODX\Revolution\modDashboardWidget->getContent(object)
MODX\Revolution\modDashboard->render(object, object)
WelcomeManagerController->process(Array ( ) )
MODX\Revolution\modManagerController->render()
MODX\Revolution\modManagerResponse->outputContent(Array ( ) )
MODX\Revolution\modManagerRequest->prepareResponse()
MODX\Revolution\modManagerRequest->handleRequest()
require(string "/Users/bochkarev/Sites/bughunt/manager/index.php")
Not compatible
I'm loving this new Extra! I tried this on a several installations now. I love how easy this is. Thank you!
I just tried to download the backup files using the Modx file manager (right click, select download). In each case, I got this error:
The website encountered an error while retrieving http://xxxxxx.com/connectors/index.php?action=browser/file/download&download=1&file=backup/xxxxxxx_xxx_20160107-151624_files.tar&HTTP_MODAUTH=modx54774f3c18ef99.79252889_1568ed6fa804bb3.51837111&source=1&wctx=undefined. It may be down for maintenance or configured incorrectly.
I am able to download the files via FireFTP with no problem.
Hosted on Hostmonster shared server
Modx is 2.4.2-pl (traditional)
PHP Version 5.4.43
On hardened installations, with a changed/custom assets_path, no backup is created.
Reason is the hard coded path to widget.css in backupMODXWidget chunk.
I just installed BackupMODX on a all-inkl hosted site. The MySQL Database backup is working without any problem - however after the backup it shows:
Backup Finished! MySQL:d01f643a_20160227-141948_mysql.sql (3.45 MB) Files:No Backup!
I've got another site where the backup is failing.
A2 Hosting
Modx 2.7.0
BackupModx 2.0.1
PHP 7.2.14
I asked the A2 Hosting tech support to look at this and this what they found.
We can't provide or debug that to the line of code level, we apologize, but form we can see here, it is trying to write onto regular /tmp folder which is not directly accessible on your type of server, and you should talk to developer to ensure that files are going to /home/xxxxxxxx/.cagefs/tmp instead (which is correct location for tmp in your case)
Error log has this:
[2019-02-19 11:13:36] (ERROR @ /home/xxxxxxxx/public_html/core/components/backupmodx/model/backupmodx/backupmodx.class.php : 98) PHP warning: filesize(): stat failed for /home/xxxxxxxx/public_html/assets/backups/2019-02-19--111335--75ce/2019-02-19--111335--75ce.sql
I've installed the plugin checked both MySQL Database and files and clicked "Backup Site" - backup works and is stored in the directory but there is no MySQL Database there.
If I only check and click "Backup Site" it reloads and shows text "No Backup" - Is that a bug with current version?
Thanks for your help.
Currently only the most recent backup can be restored via the widget.
Would it be possible to offer the user a select box or list so they can choose which backup to restore?
MODX Revo 2.8.1
BackupMODX 3.0.1
Trying Backup files, but
Error: Failing AJAX ...
again!
Dev enviroment (laragon, windows 10, MODX 3.0.1, backupmodx 3.0.5 and php 7.4.29).
Normal zip file made in root folder was about 80 Mb and backupmodx zip file about 160 Mb.
Excluded folders:
{core_path}cache/,{core_path}backup/,{core_path}packages/,{base_path}image-cache/,{assets_path}tiedostot/
Packages folder was included even I excluded it with duplicate transport zip files, and many more duplicate files around folders. And all excluded folders were in backup. Only {core_path}backup/, {base_path}image-cache/ and {assets_path}tiedostot/ were excluded.
I excluded {core_path}backup/ because there was database dump.
At the moment when restoring a backup via the widget, only the database is presented as a restore option.
It would be great if you could choose to restore both files and database.
Here is the error log:
[2018-08-01 17:01:14] (ERROR @ /home/xxxx/public_html/core/cache/includes/elements/modsnippet/105.include.cache.php : 62) PHP warning: Use of undefined constant fileLink - assumed 'fileLink' (this will throw an Error in a future version of PHP)
PHP 7.1 no errors.
Hello. In my backups i have dublicates of all filtes in core.
http://f-picture.net/lfp/s019.radikal.ru/i620/1604/6e/f5c387dab78c.png/htm
So my backup tar size is 267 Мb. Extrackt with replacement 158 Mb.
Dublicates are only in core folder. I use default params of snippet.
BackupMODX 2.0.1
Revo 2.7.0
I no longer get the AJAX error in v2.0.1 but the backup still hangs. The progress animation has been running for over 2 hours and it still hasn't completed on v.2.7.0. I've tried three different browsers and it's the same problem.
I realize this may sound silly but a client inquired about it.
Would it be possible to add a few Lexicon entries so the text on the widget can be edited? I have a client who is very particular and loves that MODX allows the editing of Lexicon entries. I told him it's not currently possible with BackupMODX but I thought I would ask just in case it was something you could add.
Specifically he would like to edit/change the following:
By the way, I know I could manually edit the text myself but it will just get overwritten the next time the Extra is updated. And I really don't want to do it over and over again.
FR: $modx->hasPermission(‘backupmodx’)
When restoring a bakup i'm presented with a list of possible backups i can choose. These bakups are labbeled by there date. However after FTP'ing an update file the modification date is changed.
On inspection i found that the date for this label is created in Backupmodx.class.php on #208.
Here the modification time of the containing folder (filemtime($this->targetPath . $folder)) is used to create the label. This should be done based on the NAME of the folder not the modification date of the folder
Is there a way to limit the backup to a selected folder on the server? I have a server I use as a sandbox of sorts that has a bunch of folders. Some of them have other Modx installations, some have other completely unrelated content. So when I run the backup, it gobbles up everything on the server, when I really just want one particular Modx installation. The resulting file can be really big.
I see there is an exclude folders parameter, but it seems I would have list every other folder in the root of the server. It would be great to specify the folder to be backed up.
Perhaps this is a one off situation for most people. I just thought I'd check.
Thanks again for a great tool!
Hi,
After the upgrade to BU 3.0.1 all my plugins are deleted when i do a restore.
I use BU to update the DB on a local MAMP from a production ENV. this worked fine in the past but since the upgrade something goes wrong while restoring the DB (i don't use it to backup files). I get a warning after restore saying 'PDO Exeption! Please read the BackupMODX errorlog for more information.
the error log says
[2019-11-05 16:28:04] (ERROR in BackupMODX @ /Users/xxx/Documents/REPOSITORY/uvaweb/clickmodel/core_uva/components/backupmodx/src/Backup/Restore.php : 49) PDO Exeption HY000 1366 Incorrect string value: '\x90fI\x02\x00\x00...' for column 'plugincode' at row 2
SQL Query: INSERT INTO `modx_site_plugins` VALUES (1,1,0,'register elements','',0,0,0,'/**\n * Created by JetBrains PhpStorm.\n * User: ralph\n * Date: 30/04/18\n * Time: 11:12 AM\n * To change this template use File | Settings | File Templates.\n *\n * DESCRIPTION\n * creates MODX elements based on text inside static files.\n * it looks trough the filesystem, finds static files and registers them as element in Modx\n * no need for a fixed file struture. the static files can be placed anywhere.\n * within the $baseDir\n *\n * PARAMETERS:\n * type:\n * chunk\n * snippet\n * template\n * plugin\n *\n * add delete:true to remove a snippet form modx based on the snippet name\n * add once:true to perform the action only once. Effectively the string SEARCHSTRING will be emptied to prevent the file from being processed each time. only with a fresh upload to server will the element be created again\n *\n *\n * USAGE in the static files:\n * <!-- YOUR SEARCHSTRING HERE{\"type\":\"chunk\",\"name\":\"TEST CHUNK\", \"categorie\":\"pinkribbon.test2.test3\"}; -->\n * <!-- YOUR SEARCHSTRING HERE{\"type\":\"chunk\",\"name\":\"TEST CHUNK\", \"categorie\":\"pinkribbon.test2.test3\", \"delete\":\"true\"}; -->\n * <!-- YOUR SEARCHSTRING HERE{\"type\":\"chunk\",\"name\":\"TEST CHUNK\", \"categorie\":\"pinkribbon.test2.test3\", \"once\":\"true\"}; -->\n *\n * So for a snippet it\'s <?php // YOUR SEARCHSTRING HERE{\"type\":\"snippet\",\"name\":\"TEST SNIPPET\", \"categorie\":\"test.test2.test3\"};\n *\n * USAGE as a snippet\n * [!register_elements]\n *\n */\n\n\n$searchstring = \'@modx-\' . \'element:\'; //the string is split to prevent THIS file from being processed by the register plugin\n$baseDir = $modx->getOption(\'register-elements-path\', null, \"staticScripts/\");\n$dir = $modx->config[\'base_path\'] . $baseDir;\n$debug = true;\n//$safetodelete = true;\n$o = \'\';\n\n\nif($debug){\n $modx->setLogLevel(modX::LOG_LEVEL_INFO);\n}\n\nif(!$modx){\n define(\'MODX_API_MODE\', true);\n require_once dirname(__FILE__) . \'/config.core.php\';\n require_once MODX_CORE_PATH . \'model/modx/modx.class.php\';\n $modx = new modX();\n $modx->initialize(\'web\');\n $modx->getService(\'error\', \'error.modError\', \'\', \'\');\n}\n\n//------ Return if the user isn\'t part of one of the allowed usergroups\n$usergroups = explode(\',\', $modx->getOption(\'elementhelper.usergroups\', null, \'Administrator\'));\nif(!$modx->user->isMember($usergroups)){\n if($debug){\n $modx->log(xPDO::LOG_LEVEL_INFO, \'Not permitted\');\n }\n return;\n}\n\n$files = getFiles($dir);\n\n\nforeach ($files as $file) {\n\n $f = fopen($file, \"r\");\n if($f){\n while (($buffer = fgets($f, 1024)) !== false) {\n preg_match(\'/\' . $searchstring . \'(.*?);/\', $buffer, $display);\n if(isset($display[1])){\n $data = json_decode($display[1], true);\n if($debug){\n // $modx->log(xPDO::LOG_LEVEL_INFO, \'process \' . $data[\"name\"]);\n }\n if(!isLocal() && !$data[\"once\"] == false){\n removeCodeline($file, $searchstring);\n }\n // prep categories\n if(isset($data[\"categorie\"])){\n $category_names = explode(\'.\', $data[\'categorie\']);\n setCategories($category_names);\n $data[\"cat\"] = get_category_id(end($category_names));\n } else {\n $data[\"cat\"] = 0;\n }\n if(isset($data[\"delete\"]) && $data[\"delete\"] == true){\n $o .= deleteElement($data);\n } else {\n $data[\"file\"] = $file;\n $o .= createElement($data);\n }\n }\n }\n\n }\n fclose($f);\n}\n$modx->log(xPDO::LOG_LEVEL_INFO, \'Finished processing elements!\');\n\n$modx->setLogLevel(modX::LOG_LEVEL_ERROR);\n\n\n//=============================================\n\nfunction isLocal(){\n $is = false;\n $locallist = array(\n \'127.0.0.1\',\n \'::1\'\n );\n if(strpos(strtolower($_SERVER[\'SERVER_NAME\']), \'dev\') === true){\n $is = true;\n }\n if(strpos(strtolower($_SERVER[\'SERVER_NAME\']), \'test\') === true){\n $is = true;\n }\n if(strpos(strtolower($_SERVER[\'SERVER_NAME\']), \'local\') === true){\n $is = true;\n }\n if(in_array($_SERVER[\'REMOTE_ADDR\'], $locallist)){\n $is = true;\n }\n return $is;\n}\n\n\nfunction removeCodeline($filename, $hit){\n $file = file($filename);\n $output = $file[0];\n $lineNumber = 0;\n foreach ($file as $lineNumber => $line) {\n if(strpos($line, $hit) !== false){\n unset($file[$lineNumber]);\n break;\n }\n }\n file_put_contents($filename, $file);\n return $output;\n}\n\nfunction get_category_id($name){\n global $modx;\n $category = $modx->getObject(\'modCategory\', array(\'category\' => $name));\n $category_id = isset($category) ? $category->get(\'id\') : 0;\n return $category_id;\n}\n\nfunction create_category($name, $parent_id = 0){\n global $modx;\n $category = $modx->getObject(\'modCategory\', array(\'category\' => $name));\n // If the category doesn\'t exist create it\n if(!isset($category)){\n $category = $modx->newObject(\'modCategory\');\n $category->set(\'category\', $name);\n }\n $category->set(\'parent\', $parent_id);\n $category->save();\n return $category;\n}\n\nfunction setCategories($cats){\n $parentcat = 0;\n foreach ($cats as $cat) {\n $newcat = create_category($cat, $parentcat);\n $parentcat = $newcat->get(\'id\');\n }\n}\n\nfunction getFiles($directory, $exempt = array(\'.\', \'..\', \'.ds_store\', \'.svn\'), &$files = array()){\n $handle = opendir($directory);\n while (false !== ($resource = readdir($handle))) {\n if(!in_array(strtolower($resource), $exempt)){\n if(is_dir($directory . $resource)){\n array_merge($files, getFiles($directory . $resource . \'/\', $exempt, $files));\n } else {\n $files[] = $directory . $resource;\n }\n }\n }\n closedir($handle);\n return $files;\n}\n\nfunction getDescriptionTime($desc){\n $l = strrpos($desc, \"-\");\n if($l > 0){\n return substr($desc, $l + 2);\n } else {\n return false;\n }\n}\n\nfunction getDescription($desc){\n $l = strrpos($desc, \"-\");\n if($l > 0){\n return substr($desc, 0, $l);\n } else {\n return $desc;\n }\n}\n\nfunction createElement($data){\n global $modx;\n global $debug;\n\n if($debug){\n $modx->log(xPDO::LOG_LEVEL_INFO, \'createElement=> \' . $data[\"name\"] . \' ,type= \' . $data[\"type\"] . \' ,categorie= \' . $data[\"categorie\"]);\n }\n switch (strtolower($data[\"type\"])) {\n case \'chunk\':\n $obj = $modx->getObject(\'modChunk\', array(\'name\' => $data[\"name\"]));\n if($obj){\n $obj = (getDescriptionTime($obj->get(\'description\')) == filemtime($data[\'file\'])) ? NULL : $obj;\n } else {\n $obj = $modx->newObject(\'modChunk\');\n $obj->set(\'name\', $data[\"name\"]);\n }\n break;\n case \'snippet\':\n $obj = $modx->getObject(\'modSnippet\', array(\'name\' => $data[\"name\"]));\n if($obj){\n $obj = (getDescriptionTime($obj->get(\'description\')) == filemtime($data[\'file\'])) ? NULL : $obj;\n\n } else {\n $obj = $modx->newObject(\'modSnippet\');\n $obj->set(\'name\', $data[\"name\"]);\n }\n break;\n case \'template\':\n $obj = $modx->getObject(\'modTemplate\', array(\'templatename\' => $data[\"name\"]));\n if($obj){\n $obj = (getDescriptionTime($obj->get(\'description\')) == filemtime($data[\'file\'])) ? NULL : $obj;\n } else {\n $obj = $modx->newObject(\'modTemplate\');\n $obj->set(\'templatename\', $data[\"name\"]);\n }\n break;\n case \'plugin\':\n $obj = $modx->getObject(\'modPlugin\', array(\'name\' => $data[\"name\"]));\n if($obj){\n $obj = (getDescriptionTime($obj->get(\'description\')) == filemtime($data[\'file\'])) ? NULL : $obj;\n } else {\n $obj = $modx->newObject(\'modPlugin\');\n $obj->set(\'name\', $data[\"name\"]);\n }\n break;\n }\n\n if($obj){\n $f = str_replace($modx->config[\'base_path\'], \"\", $data[\"file\"]);\n $obj->set(\'static\', 1);\n $obj->set(\'source\', 0);\n $obj->set(\'static_file\', $f);\n $obj->set(\'category\', $data[\'cat\']);\n $desc = getDescription($obj->get(\'description\'));\n\n if(isset($data[\'description\'])){\n $obj->set(\'description\', $data[\'description\'] . \" - \" . filemtime($data[\'file\']));\n } else {\n $obj->set(\'description\', $desc . \" - \" . filemtime($data[\'file\']));\n }\n\n $modx->log(xPDO::LOG_LEVEL_INFO, \'--- Save \' . $data[\"name\"]);\n\n $obj->setContent(file_get_contents($data[\"file\"]));\n if($obj->save()){\n // $modx->cacheManager->refresh();\n return $data[\"type\"] . \": \" . $data[\"name\"] . \' created <br>\';\n } else {\n if($debug){\n $modx->log(xPDO::LOG_LEVEL_INFO, \'FAIL Element=> \' . $data[\"name\"]);\n }\n return \'fail\';\n }\n }\n}\n\n//==============================================\nfunction deleteElement($data){\n global $modx;\n switch ($data[\"type\"]) {\n case \'chunk\':\n $obj = $modx->getObject(\'modChunk\', array(\'name\' => $data[\"name\"]));\n break;\n case \'snippet\':\n $obj = $modx->getObject(\'modSnippet\', array(\'name\' => $data[\"name\"]));\n break;\n case \'template\':\n $obj = $modx->getObject(\'modTemplate\', array(\'templatename\' => $data[\"name\"]));\n break;\n }\n if($obj){\n if($obj->remove() == false){\n return \'An error occurred while trying to remove \' . $data[\"name\"];\n } else {\n return $data[\"name\"] . \' DELETED <br>\';\n }\n }\n}',0,'a:0:{}',0,'',1,'staticScripts/plugins/registerElements.php'),(2,0,0,'TinyMCERTE','',0,1,0,'/**\n * Tiny�fI������fI���������������������`,A�������������0*A������fI��������������fI������@�������fI�������������tion(\'core_path\', null, MODX_CORE_PATH) . \'components/tinymcerte/\');\n/** @var TinyMCERTE $tinymcerte */\n$tinymcerte = $modx->getService(\n \'tinymcerte\',\n \'TinyMCERTE\',\n $corePath . \'model/tinymcerte/\',\n array(\n \'core_path\' => $corePath\n )\n);\n\n$className = \'TinyMCERTE\' . $modx->event->name;\n$modx->loadClass(\'TinyMCERTEPlugin\', $tinymcerte->getOption(\'modelPath\') . \'tinymcerte/events/\', true, true);\n$modx->loadClass($className, $tinymcerte->getOption(\'modelPath\') . \'tinymcerte/events/\', true, true);\nif (class_exists($className)) {\n /** @var TinyMCERTEPlugin $handler */\n $handler = new $className($modx, $scriptProperties);\n $handler->run();\n}\nreturn;',0,'a:0:{}',0,'',0,''),(3,0,0,'Collections','',0,4,0,'/**\n * Collections\n *\n * DESCRIPTION\n *\n * This plugin inject JS to handle proper working of close buttons in Resource\'s panel (OnDocFormPrerender)\n * This plugin handles setting proper show_in_tree parameter (OnBeforeDocFormSave, OnResourceSort)\n *\n * @var modX $modx\n * @var array $scriptProperties\n */\n$corePath = $modx->getOption(\'collections.core_path\', null, $modx->getOption(\'core_path\', null, MODX_CORE_PATH) . \'components/collections/\');\n/** @var Collections $collections */\n$collections = $modx->getService(\n \'collections\',\n \'Collections\',\n $corePath . \'model/collections/\',\n array(\n \'core_path\' => $corePath\n )\n);\n\nif (!($collections instanceof Collections)) return \'\';\n\n$className = \"\\\\Collections\\\\Events\\\\{$modx->event->name}\";\nif (class_exists($className)) {\n /** @var \\Collections\\Events\\Event $handler */\n $handler = new $className($modx, $scriptProperties);\n $handler->run();\n}\n\nreturn;',0,'a:0:{}',0,'',0,''),(4,0,0,'ImagePlus','Image+ runtime hooks - registers custom TV input & output types and includes javascripts on document edit pages.',0,7,0,'/**\n * Image+ runtime hooks\n * Registers custom TV input & output types and includes javascripts on document\n * edit pages so that the TV can be used from within other extras (i.e. MIGX,\n * Collections)\n *\n * Copyright 2013-2015 by Alan Pich <[email protected]>\n * Copyright 2015-2018 by Thomas Jakobi <[email protected]>\n *\n * @package imageplus\n * @subpackage plugin\n *\n * @author Alan Pich <[email protected]>\n * @author Thomas Jakobi <[email protected]>\n * @copyright Alan Pich 2013-2015\n * @copyright Thomas Jakobi 2015-2018\n *\n * @event OnManagerPageBeforeRender\n * @event OnTVInputRenderList\n * @event OnTVOutputRenderList\n * @event OnTVInputPropertiesList\n * @event OnTVOutputRenderPropertiesList\n * @event OnDocFormRender\n *\n * @var modX $modx\n */\n\n$eventName = $modx->event->name;\n\n$corePath = $modx->getOption(\'imageplus.core_path\', null, $modx->getOption(\'core_path\') . \'components/imageplus/\');\n/** @var ImagePlus $imageplus */\n$imageplus = $modx->getService(\'imageplus\', \'ImagePlus\', $corePath . \'model/imageplus/\', array(\n \'core_path\' => $corePath\n));\n\nswitch ($eventName) {\n case \'OnManagerPageBeforeRender\':\n $modx->controller->addLexiconTopic(\'imageplus:default\');\n $imageplus->includeScriptAssets();\n break;\n case \'OnTVInputRenderList\':\n $modx->event->output($corePath . \'elements/tv/input/\');\n break;\n case \'OnTVOutputRenderList\':\n $modx->event->output($corePath . \'elements/tv/output/\');\n break;\n case \'OnTVInputPropertiesList\':\n $modx->event->output($corePath . \'elements/tv/input/options/\');\n break;\n case \'OnTVOutputRenderPropertiesList\':\n $modx->event->output($corePath . \'elements/tv/output/options/\');\n break;\n case \'OnDocFormRender\':\n $imageplus->includeScriptAssets();\n break;\n};',0,'a:0:{}',0,'',0,''),(5,0,0,'phpThumbOfCacheManager','Handles cache cleaning when clearing the Site Cache.',0,8,0,'/*\n * Handles cache cleanup\n * pThumb\n * Copyright 2013 Jason Grant\n *\n * Please see the GitHub page for documentation or to report bugs:\n * https://github.com/oo12/phpThumbOf\n *\n * pThumb is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License as published by the Free\n * Software Foundation; either version 2 of the License, or (at your option) any\n * later version.\n *\n * pThumb is distributed in the hope that it will be useful, but WITHOUT ANY\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n * A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along with\n * phpThumbOf; if not, write to the Free Software Foundation, Inc., 59 Temple\n * Place, Suite 330, Boston, MA 02111-1307 USA\n */\n\nif ($modx->event->name === \'OnSiteRefresh\') {\n if (!$modx->loadClass(\'pThumbCacheCleaner\', MODX_CORE_PATH . \'components/phpthumbof/model/\', true, true)) {\n $modx->log(modX::LOG_LEVEL_ERROR, \'[pThumb] Could not load pThumbCacheCleaner class.\');\n return;\n }\n static $pt_settings = array();\n $pThumb = new pThumbCacheCleaner($modx, $pt_settings, array(), true);\n $pThumb->cleanCache();\n}',0,NULL,0,'',0,''),(6,0,0,'ContentBlocks','The main plugin for ContentBlocks, responsible for handling generating the form as well as saving the resource. (Part of ContentBlocks)',0,12,0,'/**\n * ContentBlocks\n *\n * Events: OnDocFormRender, OnDocFormSave\n *\n * @package contentblocks\n */\n\n$corePath = $modx->getOption(\'contentblocks.core_path\', null, $modx->getOption(\'core_path\') . \'components/contentblocks/\');\n$assetsUrl = $modx->getOption(\'contentblocks.assets_url\', null, $modx->getOption(\'assets_url\') . \'components/contentblocks/\');\n\n/**\n * @var ContentBlocks $ContentBlocks\n * @var modResource $resource\n * @var modX $modx\n * @var array $scriptProperties\n */\n$ContentBlocks = $modx->getService(\'contentblocks\', \'ContentBlocks\', $corePath . \'model/contentblocks/\');\n\nswitch ($modx->event->name) {\n case \'OnDocFormPrerender\':\n if ($modx->controller && isset($modx->controller->resource) && $modx->controller->resource instanceof modResource) {\n $resource = $modx->controller->resource;\n $ContentBlocks->setResource($modx->controller->resource);\n }\n else {\n return;\n }\n\n // Default settings\n $disabled = (int)$modx->getOption(\'contentblocks.disabled\', null, false);\n $acceptedResourceTypes = $modx->getOption(\'contentblocks.accepted_resource_types\', null, \'modDocument,mgResource\');\n\n // Fake the wctx variable for loading the working context to get settings\n if (!isset($_GET[\'wctx\'])) $_GET[\'wctx\'] = $resource->get(\'context_key\');\n\n // If we got the working context, get some settings\n if ($modx->controller->loadWorkingContext()) {\n $disabled = (int)$modx->controller->workingContext->getOption(\'contentblocks.disabled\', $disabled);\n $acceptedResourceTypes = $modx->controller->workingContext->getOption(\'contentblocks.accepted_resource_types\', $acceptedResourceTypes);\n }\n\n // Check if we\'re using an allowed resource type\n $acceptedType = false;\n $acceptedResourceTypes = explode(\',\', $acceptedResourceTypes);\n foreach ($acceptedResourceTypes as $type) {\n if ($resource instanceof $type) $acceptedType = true;\n }\n\n // If contentblocks is disabled or this is not an accepted resource, we can stop here.\n if ($disabled || !$acceptedType) return;\n\n // Load the lexicon\n $modx->controller->addLexiconTopic(\'contentblocks:default\');\n $isContentBlocks = $resource->getProperty(\'_isContentBlocks\', \'contentblocks\', null);\n\n // Load the use_contentblocks setting\n if ($ContentBlocks->getOption(\'contentblocks.show_resource_option\', null, true)) {\n $modx->controller->addJavascript($assetsUrl . \'cmp/js/widgets/booleancombo.js\');\n $settingChunk = $modx->newObject(\'modChunk\', array(\n \'content\' => file_get_contents($corePath . \'templates/setting.tpl\')\n ));\n\n $modx->controller->addHtml($settingChunk->process(array(\n \'value\' => ($isContentBlocks !== false) ? \'1\' : \'0\'\n )));\n }\n\n // Halt if we\'re not using contentblocks here\n if ($isContentBlocks === false) {\n // we\'re done here\n return;\n }\n\n // Prepare the content\n $contents = array();\n if ($isContentBlocks) {\n // When reloading, the contentblocks field will contain the JSON data\n $contents = $resource->get(\'contentblocks\');\n if (empty($contents)) {\n // If it\'s empty, we get the data from the resource property instead\n $contents = $resource->getProperty(\'content\', \'contentblocks\');\n }\n\n // Try to decode the JSON\n $contents = $modx->fromJSON($contents);\n }\n\n if (!is_array($contents) || empty($contents)) {\n $content = $resource->get(\'content\');\n $contents = $ContentBlocks->getDefaultCanvas(false, $content);\n }\n\n // Generate a wrapper class to apply, so we can target stuff in CSS\n $wrapperCls = array();\n $wrapperCls[] = \'type_\' . strtolower($resource->get(\'class_key\'));\n $wrapperCls[] = \'position_\' . $ContentBlocks->config[\'canvas_position\'];\n $modxVersion = $modx->getVersionData();\n if (version_compare($modxVersion[\'full_version\'], \'2.3.0-dev\', \'>=\')) {\n $wrapperCls[] = \'modx_v23\';\n }\n if (version_compare($modxVersion[\'full_version\'], \'3.0.0-dev\', \'>=\')) {\n $wrapperCls[] = \'modx_v30\';\n }\n $wrapperCls = implode(\' \', $wrapperCls);\n\n // Grab objects for building the canvas\n $objects = $ContentBlocks->getObjectsForCanvas($resource);\n $categories = $modx->toJSON($objects[\'categories\']);\n $fields = $modx->toJSON($objects[\'fields\']);\n $layouts = $modx->toJSON($objects[\'layouts\']);\n $templates = $modx->toJSON($objects[\'templates\']);\n\n $contents = $modx->toJSON($contents);\n $resourceInfo = $modx->toJSON($resource->get(array(\'id\', \'pagetitle\', \'context_key\')));\n $config = $modx->toJSON($ContentBlocks->config);\n\n $modx->controller->addHtml(<<<HTML\n<script type=\"text/javascript\">\n var ContentBlocksCategories = $categories,\n ContentBlocksFields = $fields,\n ContentBlocksLayouts = $layouts,\n ContentBlocksTemplates = $templates,\n ContentBlocksContents = $contents,\n ContentBlocksConfig = $config,\n ContentBlocksWrapperCls = \"$wrapperCls\",\n ContentBlocksResource = $resourceInfo;\n\n var cbGenerated = false,\n ContentBlocksWillRenderContent = true;\n MODx.on(\'ready\', function () {\n // Prevent double-generation\n if (cbGenerated) return;\n cbGenerated = true;\n\n ContentBlocks.render();\n\n // Hook up to beforesubmit to fetch the values and fetch the content blocks\n Ext.getCmp(\'modx-panel-resource\').on(\'beforesubmit\', function(o) {\n o.form.baseParams[\'contentblocks\'] = ContentBlocks.getData();\n });\n });\n</script>\nHTML\n );\n $scriptTags = $ContentBlocks->getAssets();\n $modx->controller->addHtml($scriptTags);\n\n break;\n\n case \'OnDocFormSave\':\n $ContentBlocks->setResource($resource);\n $modx->resource = $resource;\n\n $cbJson = $resource->get(\'contentblocks\');\n\n $cbContent = $modx->fromJSON($cbJson);\n\n // RenderContent Event\n $response = $modx->invokeEvent(\'ContentBlocks_RenderContent\', array(\n \'cbContent\' => $cbContent,\n \'cbJson\' => $cbJson,\n \'resource\' => $resource\n ));\n // check if customized content was returned\n if (!empty($response) && is_array($response) && json_encode($response) !== \'[\"\"]\') {\n $cbContent = $response[0][\'cbContent\'];\n $cbJson = $response[0][\'cbJson\'];\n }\n\n if (!empty($cbJson) && $cbContent !== false && is_array($cbContent)) {\n $summary = $ContentBlocks->summarizeContent($cbContent);\n $resource->setProperties(array(\n \'content\' => $cbJson,\n \'linear\' => $summary[\'linear\'],\n \'fieldcounts\' => $summary[\'fieldcounts\'],\n \'_isContentBlocks\' => true,\n ), \'contentblocks\', true);\n\n // We save the CB data as soon as possible ...\n $resource->save();\n // ... then we parse it to HTML which is stored in the content ...\n try {\n $ContentBlocks->loadParser();\n $resource->setContent($ContentBlocks->generateHtml($cbContent));\n $ContentBlocks->restoreParser();\n } catch (Exception $e) {\n $modx->log(modX::LOG_LEVEL_ERROR, \'Exception while trying to parse the content of resource \' . $resource->id . \': \' . $e->getMessage());\n }\n // ... to make sure parse errors don\'t lose the content.\n }\n $resource->set(\'contentblocks\', \'\');\n\n // Make sure we need to continue to use contentblocks\n $useCb = $resource->get(\'use_contentblocks\');\n if (in_array($useCb, array(\'0\', \'1\'), true)) {\n $resource->setProperty(\'_isContentBlocks\', (bool)$useCb, \'contentblocks\');\n }\n $resource->save();\n break;\n\n /**\n * @var string $path\n */\n case \'OnFileManagerFileRename\':\n $ContentBlocks->renames[] = $path;\n break;\n}\n\nreturn;',0,NULL,0,'',0,''),(7,1,0,'pdoTools','',0,17,0,'/** @var modX $modx */\nswitch ($modx->event->name) {\n\n case \'OnMODXInit\':\n $fqn = $modx->getOption(\'pdoTools.class\', null, \'pdotools.pdotools\', true);\n $path = $modx->getOption(\'pdotools_class_path\', null, MODX_CORE_PATH . \'components/pdotools/model/\', true);\n $modx->loadClass($fqn, $path, false, true);\n\n $fqn = $modx->getOption(\'pdoFetch.class\', null, \'pdotools.pdofetch\', true);\n $path = $modx->getOption(\'pdofetch_class_path\', null, MODX_CORE_PATH . \'components/pdotools/model/\', true);\n $modx->loadClass($fqn, $path, false, true);\n break;\n\n case \'OnSiteRefresh\':\n /** @var pdoTools $pdoTools */\n if ($pdoTools = $modx->getService(\'pdoTools\')) {\n if ($pdoTools->clearFileCache()) {\n $modx->log(modX::LOG_LEVEL_INFO, $modx->lexicon(\'refresh_default\') . \': pdoTools\');\n }\n }\n break;\n\n case \'OnWebPagePrerender\':\n $parser = $modx->getParser();\n if ($parser instanceof pdoParser) {\n foreach ($parser->pdoTools->ignores as $key => $val) {\n $modx->resource->_output = str_replace($key, $val, $modx->resource->_output);\n }\n }\n break;\n}',0,NULL,0,'',0,'core/components/pdotools/elements/plugins/plugin.pdotools.php'),(8,1,0,'turnoff CB','',0,0,0,'$eventName = $modx->event->name;\nswitch($eventName) {\n case \'OnDocFormPrerender\':\n $resource = $modx->controller->resource;\n $disabled = false;\n $disabledTemplates = array(6);\n if (in_array($resource->get(\'template\'), $disabledTemplates)) {\n $disabled = true;\n }\n if ($disabled) {\n $resource->setProperty(\'_isContentBlocks\', false, \'contentblocks\');\n }\n break; \n}',0,'a:0:{}',0,'',0,''),(9,0,0,'Tagger','',0,24,0,'/**\n * Tagger\n *\n * DESCRIPTION\n *\n * This plugin inject JS to add Tab with tag groups into Resource panel\n */\n\n$corePath = $modx->getOption(\'tagger.core_path\', null, $modx->getOption(\'core_path\', null, MODX_CORE_PATH) . \'components/tagger/\');\n/** @var Tagger $tagger */\n$tagger = $modx->getService(\n \'tagger\',\n \'Tagger\',\n $corePath . \'model/tagger/\',\n array(\n \'core_path\' => $corePath\n )\n);\n\n$className = \'Tagger\' . $modx->event->name;\n$modx->loadClass(\'TaggerPlugin\', $tagger->getOption(\'modelPath\') . \'tagger/events/\', true, true);\n$modx->loadClass($className, $tagger->getOption(\'modelPath\') . \'tagger/events/\', true, true);\n\nif (class_exists($className)) {\n /** @var TaggerPlugin $handler */\n $handler = new $className($modx, $scriptProperties);\n $handler->run();\n}\n\nreturn;',0,'a:0:{}',0,'',0,''),(10,0,0,'XRouting','XRouting is a simple plugin that handles requests for different contexts. It automatically switches the context based on a (sub)domain AND/OR subfolder.',0,0,0,'switch ($modx->event->name) {\n\n // \"refresh cache\" part\n case \'OnContextSave\':\n case \'OnContextRemove\':\n case \'OnSiteRefresh\':\n \n $contexts = array();\n $cacheKey = \'xrouting_contextmap\';\n $cacheOptions = array();\n \n // build context array\n $query = $modx->newQuery(\'modContext\');\n $query->where(array(\'modContext.key:NOT IN\' => array(\'mgr\')));\n $query->sortby($modx->escape(\'modContext\') . \'.\' . $modx->escape(\'key\'), \'DESC\');\n $contextsGraph = $modx->getCollectionGraph(\'modContext\', \'{\"ContextSettings\":{}}\', $query);\n \n foreach ($contextsGraph as $context) {\n $contextSettings = array();\n foreach ($context->ContextSettings as $cSetting) {\n $contextSettings[$cSetting->get(\'key\')] = $cSetting->get(\'value\');\n }\n \n if (!empty($contextSettings[\'http_host\']) && !empty($contextSettings[\'base_url\'])) {\n \n // add http_host to hosts list\n $contexts[\'_hosts\'][$contextSettings[\'http_host\']][] = $context->get(\'key\');\n \n // add alias hosts to host list\n if (!empty($contextSettings[\'http_host_aliases\'])) {\n foreach (explode(\',\',$contextSettings[\'http_host_aliases\']) as $alias) {\n $contexts[\'_hosts\'][$alias][] = $context->get(\'key\');\n }\n }\n \n // add context settings\n $contexts[$context->get(\'key\')] = $contextSettings;\n }\n }\n \n unset($contextsGraph);\n $modx->cacheManager->set($cacheKey, $contexts, 0, $cacheOptions);\n break;\n \n \n // \"routing\" part\n default:\n case \'OnHandleRequest\':\n if ($modx->context->get(\'key\') == \'mgr\') return;\n \n $contexts = array();\n \n $cacheKey = \'xrouting_contextmap\';\n $cacheOptions = array();\n $contexts = $modx->cacheManager->get($cacheKey, $cacheOptions);\n \n if (empty($contexts)) {\n // build context array\n $query = $modx->newQuery(\'modContext\');\n $query->where(array(\'modContext.key:NOT IN\' => array(\'mgr\')));\n $query->sortby($modx->escape(\'modContext\') . \'.\' . $modx->escape(\'key\'), \'DESC\');\n $contextsGraph = $modx->getCollectionGraph(\'modContext\', \'{\"ContextSettings\":{}}\', $query);\n \n foreach ($contextsGraph as $context) {\n $contextSettings = array();\n foreach ($context->ContextSettings as $cSetting) {\n $contextSettings[$cSetting->get(\'key\')] = $cSetting->get(\'value\');\n }\n \n if (!empty($contextSettings[\'http_host\']) && !empty($contextSettings[\'base_url\'])) {\n \n // add http_host to hosts list\n $contexts[\'_hosts\'][$contextSettings[\'http_host\']][] = $context->get(\'key\');\n \n // add alias hosts to host list\n if (!empty($contextSettings[\'http_host_aliases\'])) {\n foreach (explode(\',\',$contextSettings[\'http_host_aliases\']) as $alias) {\n $contexts[\'_hosts\'][$alias][] = $context->get(\'key\');\n }\n }\n \n // add context settings\n $contexts[$context->get(\'key\')] = $contextSettings;\n }\n }\n \n unset($contextsGraph);\n $modx->cacheManager->set($cacheKey, $contexts, 0, $cacheOptions);\n }\n\n\n if (!empty($contexts)) {\n $http_host = $_SERVER[\'HTTP_HOST\'];\n if ($modx->getOption(\'xrouting.include_www\', null, true)) {\n $http_host = str_replace(\'www.\',\'\',$http_host);\n }\n \n $modx_base_url = $modx->getOption(\'base_url\', null, MODX_BASE_URL);\n $requestUrl = str_replace(\'//\',\'/\',$modx_base_url.$_REQUEST[$modx->getOption(\'request_param_alias\', null, \'q\')]);\n $matches = array();\n \n \n // find matching hosts\n $matched_contexts = $contexts[\'_hosts\'][$http_host];\n \n \n foreach ((array) $matched_contexts as $index => $ckey) {\n \n $context = $contexts[$ckey];\n $strpos = strpos($requestUrl, $contexts[$ckey][\'base_url\']);\n if ($strpos === 0) {\n $matches[strlen($contexts[$ckey][\'base_url\'])] = $ckey;\n }\n }\n\n // modify request for the matched context\n if (!empty($matches)) {\n \n $cSettings = $contexts[$matches[max(array_keys($matches))]];\n $cKey = $matches[max(array_keys($matches))];\n \n // do we need to switch the context?\n if ($modx->context->get(\'key\') != $cKey) {\n $modx->switchContext($cKey);\n }\n \n // remove base_url from request query\n if ($cSettings[\'base_url\'] != $modx_base_url) {\n $newRequestUrl = str_replace($cSettings[\'base_url\'],\'\',$requestUrl);\n $_REQUEST[$modx->getOption(\'request_param_alias\', null, \'q\')] = $newRequestUrl;\n }\n \n \n } else if ($_REQUEST[\'xrouting-debug\'] != \'1\' || !$modx->getOption(\'xrouting.allow_debug_info\', null, false)) {\n // if no match found\n if ($modx->getOption(\'xrouting.show_no_match_error\', null, true)) {\n $modx->sendErrorPage();\n } else {\n $modx->switchContext($modx->getOption(\'xrouting.default_context\', null, \'web\'));\n }\n \n }\n \n // output debug info\n if ($_REQUEST[\'xrouting-debug\'] == \'1\' && $modx->getOption(\'xrouting.allow_debug_info\', null, false)) {\n $debuginfo = \'<pre>\';\n $debuginfo .= \"## MODX context map:\\n\\n\" . print_r($contexts,true) . \"\\n\\n\\n\";\n $debuginfo .= \"## Requested URL: \" . $_REQUEST[$modx->getOption(\'request_param_alias\', null, \'q\')] . \"\\n\\n\\n\";\n $debuginfo .= \"## Requested URL with base_url: \". $requestUrl .\"\\n\\n\\n\";\n $debuginfo .= \"## Matched context(s) (Array key defines match quality):\\n\\n\" . print_r($matches,true) . \"\\n\\n\\n\";\n $debuginfo .= \"## Request will go to context: \" . $matches[max(array_keys($matches))] . \"\\n\\n\\n\";\n $debuginfo .= \"## Modified request URL: \" . $newRequestUrl . \"\\n\\n\\n\";\n die($debuginfo);\n }\n }\n break;\n}',0,NULL,0,'',0,''),(12,0,0,'ClientConfig','Sets system settings from the Client Config CMP.',0,0,0,'/**\n * ClientConfig\n *\n * Copyright 2011-2014 by Mark Hamstra <[email protected]>\n *\n * ClientConfig is free software; you can redistribute it and/or modify it under the\n * terms of the GNU General Public License as published by the Free Software\n * Foundation; either version 2 of the License, or (at your option) any later\n * version.\n *\n * ClientConfig is distributed in the hope that it will be useful, but WITHOUT ANY\n * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n * A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along with\n * ClientConfig; if not, write to the Free Software Foundation, Inc., 59 Temple\n * Place, Suite 330, Boston, MA 02111-1307 USA\n *\n * @package clientconfig\n *\n * @var modX $modx\n * @var int $id\n * @var string $mode\n * @var modResource $resource\n * @var modTemplate $template\n * @var modTemplateVar $tv\n * @var modChunk $chunk\n * @var modSnippet $snippet\n * @var modPlugin $plugin\n*/\n\n$eventName = $modx->event->name;\n\nswitch($eventName) {\n case \'OnMODXInit\':\n case \'OnHandleRequest\':\n case \'pdoToolsOnFenomInit\':\n /* Grab the class */\n $path = $modx->getOption(\'clientconfig.core_path\', null, $modx->getOption(\'core_path\') . \'components/clientconfig/\');\n $path .= \'model/clientconfig/\';\n $clientConfig = $modx->getService(\'clientconfig\',\'ClientConfig\', $path);\n\n /* If we got the class (gotta be careful of failed migrations), grab settings and go! */\n if ($clientConfig instanceof ClientConfig) {\n $contextKey = $modx->context instanceof modContext ? $modx->context->get(\'key\') : \'web\';\n $settings = $clientConfig->getSettings($contextKey);\n\n /* Make settings available as [[++tags]] */\n $modx->setPlaceholders($settings, \'+\');\n\n /* Make settings available for $modx->getOption() */\n foreach ($settings as $key => $value) {\n $modx->setOption($key, $value);\n }\n }\n break;\n}\n\nreturn;',0,NULL,0,'',0,'');
Any idea why?
tnx
RDG
Hello,
thanks for the great extra. It works very well!
But, to use it on a all-inkl.com Shared-/Root-Host you have to activate "/bin/pktar" as alias for "tar" (line 88/93) over the support. Maybe you can add a note in the docs.
Thanks very much for this extra!
Jens
This issue appears here on:
BackupMODX 3.0.1-pl
Litespeed 5.3.8
MODX 2.6.1 and 2.7.1
PHP 5.6.40 and 7.2.22
When making backup core/packages (permissions, 755) is not being added to the archive.
I note this across several MODX 2.7.1 installations and a 2.6.1 installation.
Hello. Thanks for your modx plugin.
I have a problem with BackupModx, or maybe a logical I don't understand.
I use the plugin with a cronjob. I activate the option for files and database to be clean when a same number limit is reached. For me it would be logical to only have the older files erased. But instead all files and the backup folder are deleted.
Do I have forgot something?
After download the package, installation breaks every time at the same point:
Attempting to preserve files at /usr/local/www/apache24/noexec/www.....de/core/components/backupmodx into archive /usr/local/www/apache24/noexec/www.....de/core/packages/backupmodx-3.0.4-pl/modCategory/c2c106616dd2f4b8a6ff1432dc0cb872.1.preserved.zip
MODX-Version: 2.8.3
PHP: 7.3
Does not create backup files. Widget shows "Files (0 MB)."
A folder with the file named like "ziejjYvj" is created in the directory "core/components/backupmodx/backups/", but if press button "Restore a Backup", a row with files don't appear in the list.
No any error in logs. The MySQL Database backup is working.
What could be the problem?
I always have problems to unzip the created zipped files (for example XYZ_files.tar).
I use WinZip.
This is the error message:
Fehler: Das System kann den angegebenen Pfad nicht finden.
kann D:\...\core\packages\contentblocks-1.7.5-pl\modCategory\cdecf9112376ad7249b9dfe6be8023c8\0\contentblocks\model\vendor\modmore\alpacka\core\components\alpacka\vendor\composer\autoload_namespaces.php nicht erstellen
Schwerer Fehler: Dateierstellung fehlgeschlagen.
Where could this be the problem?
Is there a possibility to create a .zip file instead of .tar?
I just tried to backup a site and got this message in the widget. The DB was not backed up.
Usage: mysqldump [OPTIONS] database [tables] OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] OR mysqldump [OPTIONS] --all-databases [OPTIONS] For more options, use mysqldump --help
This appeared in the modx error log.
[2016-04-28 14:14:06] (ERROR @ /homexxx/xxxxxxx/public_html/core/cache/includes/elements/modsnippet/57.include.cache.php : 117) PHP warning: filesize(): stat failed for /homexxx/xxxxxxx/public_html/assets/backup/xxxxxxxx_modx2_20160428-141406_mysql.sql
When I manually exported the DB it was 22mb.
Hostmonster Shared hosting
Modx 2.4.2
PHP Ver 5.4.43
I've already added a couple of other feature requests, this is the last one I promise! :)
It would be excellent to have a "Download Backup" button at the bottom of the widget (next to "Backup Site" and "Restore Backup" buttons).
Clicking on the button would present the user with a list of all current backups and they could choose to download any of them directly.
I will describe my actions. Developed a subdomain site, on a different database. After the site was uploaded to the working domain, changed the path, changed the configuration files and changed the settings to a new (clean) database. There are no errors, the site works well on a new basis.
But when I try to create a backup of the database, I get a file of 0 megabytes. Please tell me what and where can it work wrong? After all, the site itself works well, the paths are all correct and both databases are on the same server.
P.S.
Files backup works fine!
I will be glad to any answer!
MODX 2.7.1
BackupMODX 2.0.1 PL
PHP 7.2
MySQL 5.7.21-20
Thanks!
Hi.
First of all. Thanks for this extra! Does its job nice and smooth. With Bob Rays UpgradeModx, Modx now have tools that should be in core for years.
But I have issue that might be a dangerous for backup purposes. Happened in multiple sites.
When try to download database file from dashboard link, downloads file is containing error page template code. Method to download is click with second mouse button and "Save target to disk...". If you accidentally click link normal way, it returns 404 error page.
Database file size shows as it should be in dashboard, but downloaded file is small. And when file is opened in notepad it is sites error page template code.
Other downloads ok from dashboard. In combined file database was ok.
From file tree all downloads ok.
System info:
BackupModx: 1.0.5-beta
MODX Revolution 2.5.7-pl (traditional)
Apache version 2.4.12
PHP Version: 5.4.42
Database type: mysql
System: Linux 2.6.32-642.4.2.el6.x86_64
I did a fresh install of 3.0.0 and when I try to run it from the home screen I get "Error creating target path!" as the result. I checked and nginx has write access to the folder I specified during the install.
Ignore modx_sessions and modx_manager_logs tables of Backup
First: Thank you for this great extra - and version 2! 😄
The widget name changed from "Backup MODX" to "BackupMODX". On upgrade, this causes, I assume, the creation of a new/second widget.
I always get the error message "Uncaught Error: Call to a member function close()" when I try to backup files, but fine with database.
PHP warning: tempnam(): open_basedir restriction in effect. File(/tmp) is not within the allowed path(s): (/var/www/u983985/data:.)
Tried this extra and it seems very promising. But I noticed few things in it.
Backup files of files is twice bigger than CPanels zip files. CP zip file 35 MB versus smallest file backup at same site about 75 MB. Combined backup is twice bigger than smaller file (about 145 MB).
Together those files get smaller servers over their quota easily.
Possibility to select backup without combined backup or something would be cool.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.