Composr Supplementary: Professional upgrading
Written by Chris Graham
Potentially Outdated Tutorial
This supplementary tutorial might be outdated as it was written with ocProducts, Ltd (a now defunct company) in mind. As of version 11, Composr CMS is not commercially-backed (but companies and individuals can hire each other to develop Composr features).
This tutorial provides a professional process for updating customer website(s). Steps here may also be useful for professional website "tune ups".
It is only intended for programmers who are experienced in the use of Composr.
Table of contents
Getting organised
If you are updating multiple websites then create a spreadsheet with the following columns:- Website URL
- Prospective upgrade date
- Cost quote
- Website owner name
- Website owner e-mail
- Support ticket / CRM URL
- Contacted owner?
- Have access to website?
- Cost agreed with owner?
- Any concerns
This will keep you organised and prevent you from losing your sanity trying to remember all these details.
Process
This is the process repeated for each website being upgraded. The steps are not set in stone, but rather designed to be interpreted as guidelines by an experienced developer.We assume you are running your own local AMP-style stack, have Git installed, and have a Composr Git checkout under <webroot>/Composr
<webroot> refers to your webroot, wherever it is. On my machine it is ~/www.
Step | Description | Extra code / notes |
---|---|---|
1 | Transfer these instructions to a separate TODO list so you can work through them | Copy to clipboard · Personalise paths |
Downloading, assessing, reconfiguring
|
||
2 | Check for any special circumstances | If a multi-site-network or a third-party forum is involved, or other third-party integrations, extra consideration for compatibility will be needed |
3 | Make sure the website owner is aware that an upgrade cost doesn't include training for functionality changes | Customers need to be aware of costs, if you don't protect yourself you could have a customer expecting you to include days of free training for what you're only invoicing as a few hours of work. Customers also need to be aware that things may change, including features being removed (link them to any announcement about this). Consider also asking for a list of all the design or code changes made on the site so that you can cost it up / plain it; anything non-listed might be charged extra for. |
4 | Download all the website files to your local machine, under <webroot>/<codename> | It's much more efficient to work locally. Leave this running in the background while you work on other steps / tasks. |
5 | Check the remote server meets the Composr minimum requirements |
If the requirements are not met you'll need to circle back to the website owner; they may have intentionally held back software on their hosting and have the capability to update it, or they may need to do a server upgrade or host switch. Run the first two steps of Composr's installer and see if it complains about anything (almost all requirements are checked by it). |
6 | Confirm the remote site is running a version of Composr that you can upgrade from | If not you'll need to circle back and inform them of the cost of jumping through other intermediate Composr version(s). |
† 7 | Create <webroot>/<codename>/_temp and put a .htaccess file in it |
CodeRequire all denied |
† 8 | Download the website database to your local machine, put it in <webroot>/<codename>/_temp/initial.sql |
If you can't access phpMyAdmin, then use a script:Code (PHP)<?php
$filename = 'initial.sql'; $h = 'Content-Disposition: attachment; filename="' . $filename . '"'; header($h); $db_site = 'TODO'; $db_site_host = 'localhost'; $db_site_user = 'TODO'; $db_site_password = 'TODO'; if ($db_site == 'TODO') { require('_config.php'); $db_site = $SITE_INFO['db_site']; $db_site_host = $SITE_INFO['db_site_host']; $db_site_user = $SITE_INFO['db_site_user']; $db_site_password = $SITE_INFO['db_site_password']; } $sql_cmd = 'mysqldump'; $sql_cmd .= ' -u' . escapeshellarg($db_site_user); $sql_cmd .= ' -p' . escapeshellarg($db_site_password); $sql_cmd .= ' -h' . escapeshellarg($db_site_host); $sql_cmd .= ' ' . escapeshellarg($db_site); $sql_cmd .= ' 2>&1 > ' . $filename; echo '/*'; echo shell_exec($sql_cmd); echo '*/'; @ob_end_clean(); readfile($filename); unlink($filename); if (!empty($_GET['self_destruct'])) { unlink('sqldump.php'); } |
9 | If your server is not suEXEC-style, set recursive world write permissions |
Code (Bash)cd <webroot>/<codename> sudo chmod -R 777 . |
† 10 | (Following directly from the above) Change utf8mb4 to utf8 for just the following tables: cms_addons, cms_f_saved_warnings, cms_gsp, cms_wordfilter, cms_import_parts_done, cms_msp, cms_newsletter_subscribe, cms_theme_images, and cms_tickets | If you are having to fudge a server running an old version of MySQL, use utf8 instead and be ready to tell the website owner they cannot use emojis. |
† 11 | Import the SQL dump into your local MySQL installation, in a database named client_<codename>, using the command line mysql client |
Code (Bash)cd <webroot>/<codename> mysql client_<codename> < _temp/stage1.sql |
12 | Reconfigure _config.php to have local details by putting local ones on your development hostname |
Code (PHP)$host = gethostname(); switch ($host) { case 'TODO': // dev machine unset($SITE_INFO['db_forums']); unset($SITE_INFO['db_forums_host']); unset($SITE_INFO['db_forums_user']); unset($SITE_INFO['db_forums_password']); unset($SITE_INFO['cns_table_prefix']); unset($SITE_INFO['cookie_domain']); unset($SITE_INFO['cookie_path']); $SITE_INFO['base_url'] = 'http://localhost/<codename>'; $SITE_INFO['db_site'] = 'client_<codename>'; $SITE_INFO['db_site_host'] = 'localhost'; $SITE_INFO['db_site_user'] = 'root'; $SITE_INFO['db_site_password'] = ''; $SITE_INFO['debug_mode'] = '0'; $SITE_INFO['dev_mode'] = '0'; $SITE_INFO['no_email_output'] = '1'; // These must not exist on any live site, // they allow temporary unauthenticated // local admin access to make upgrading // easier a third-party developer $SITE_INFO['admin_password'] = ''; $SITE_INFO['backdoor_ip'] = '127.0.0.1'; break; } |
13 | Set up a local Git repository to reduce the chance of losing work |
Code (Bash)cd <webroot>/<codename> git init cp <webroot>/composr/.gitignore . Code (Bash)git add . git commit -a -m "Initial commit" |
Main upgrade
|
||
† 14 | Log into the website's upgrader on your local machine | |
† 15 | Empty the caches | |
16 | Do the file transfer via a custom upgrader build | |
17 | Do the integrity checker scan and delete files from the prior version | |
† 18 | Do the database upgrade | |
Cleanup and quarantine
|
||
19 | Save a new SQL dump into the _temp folder |
Code (Bash)cd <webroot>/<codename> mysqldump client_<codename> > _temp/stage2.sql |
20 | Delete old page revisions, old config files, old backups, old .latest_in_cms_edit files, etc | |
21 | Temporarily move any custom themes into a parallel directory structure under _old; use the integrity check in the upgrader to quarantine alien files, which will also move them under _old | |
† 22 | If jumping across versions run through the "Correct MySQL schema issues (for developers only)" tool in the upgrader to find and resolve any unexpected issues that might have developed | Don't just trust the SQL given, check it really is correct to repair the problems found. |
23 | Run some cleanup tools | Go to Admin Zone > Tools > Cleanup tools, run "Sync for lost disk content" and "Theme Wizard files"; if you're really enthusiastic also "Find orphaned uploads" and "Broken URLs" |
24 | Consider replacing all the TAR files in addons/imports so you're sure they're fresh | If you download a custom upgrade package you can find all the TAR files in it (the from version number in the URL is irrelevant) |
25 | Do a Git commit |
Code (Bash)cd <webroot>/<codename> git add . git commit -a -m "Finished cleanup and quarantine" |
Rebuild custom code and design
|
||
26 | Build a new theme with the correct seed. | |
27 | Use a diff tool to find all the changes made in the old theme (you put them in _old). |
You can usually diff-compare against the .editfrom files, otherwise you'll need to go back and compare with the originals from the version you are upgrading from. There is a themechanges.sh script which may be useful, but realistically you probably just want to do it yourself on a file-by-file basis. |
28 | Fix for specific known theme changes. | |
29 | Use a diff tool to find all the changes made in code files you put in _old. | You'll need to compare overrides against the originals from the version you are upgrading from. Custom code and overridden code will need to be assessed to make sure it still is valid. By the time you're done you should be able to erase the _old directory. |
30 | Run CQC. | Run the Code Quality Checker on any custom code. Do this by copying data_custom/functions.bin from a Composr GitLab pull, and then run the CQC out of that GitLab pull while reconfiguring the scan folder to the <webroot>/<codename> directory. |
31 | Do final local testing. | Go through testing page by page, and also at least get a feel for content (such as news articles) working well. |
32 | Review errorlog.php then clear it out | |
33 | Do a Git commit |
Code (Bash)cd <webroot>/<codename> git add . git commit -a -m "Finished code rebuild" |
Get back in sync
|
Defer this section if you are going to provide a client demo before the final upgrade | |
34 | Close the remote site. | If the site being upgraded has database content changing regularly (perhaps member activity), you need to update your local database so you have those changes. Skip this and the next step if you do not. |
35 | Get your database back in sync |
Do one of 3 things:
|
36 | If the site being upgraded has files changing regularly (perhaps edited Comcode pages), download those changed files and extract locally |
This is a script to identify changed remote files and ZIP them:Code (PHP)<?php /*
Composr Copyright (c) Christopher Graham, 2004-2024 See docs/LICENSE.md for full licensing information. Meta Script: Find files modified within the last 'days' days */ header('Content-Type: text/plain'); if (!isset($_GET['days'])) { exit('Must give a days parameter'); } $days = intval($_GET['days']); $cutoff = time() - 60 * 60 * 24 * $days; if (isset($_GET['path'])) { chdir($_GET['path']); } $files = array(); $out = do_dir('.'); sort($out); foreach ($out as $file) { if (filemtime($file) > $cutoff) { $files[] = $file; } } if (!empty($_GET['zip'])) { if (empty($files)) { exit('No files'); } header('Content-Type: application/octet-stream'); $h = 'Content-Disposition: attachment; filename="new_files.zip"'; header($h); $cmd = 'zip new_files.zip'; foreach ($files as $file) { $cmd .= ' ' . escapeshellarg($file); } shell_exec($cmd); @ob_end_clean(); readfile('new_files.zip'); unlink('new_files.zip'); exit(); } foreach ($files as $file) { echo $file . chr(10); } echo 'Done; set &zip=1 to download a ZIP file'; if (!empty($_GET['self_destruct']) { unlink('find_new_files.php'); } function do_dir($dir) { $out = array(); $_dir = ($dir == '') ? '.' : $dir; $dh = opendir($_dir); if ($dh) { while (($file = readdir($dh)) !== false) { if ($file[0] == '.') { continue; } if (is_file($_dir . '/' . $file)) { $out[] = $_dir . '/' . $file; } elseif (is_dir($_dir . '/' . $file)) { $_under = $dir . (($dir != '') ? '/' : '') . $file; $_out = do_dir($_under); $out = array_merge($out, $_out); } } } return $out; } |
Uploading
|
||
37 | Put a copy of bigdump.php into the _temp folder and configure it for the live database | http://www.ozerov.de/bigdump/ |
38 | Upload a ZIP of the files into a _new folder, being careful to not include the .git folder in the ZIP |
If some upload directories are too big, omit them and resolve this by moving back the old ones from the live server. For a further level of professionalism you may choose to deploy using your Git repository rather than a ZIP file, if so push Git up to a shared repository (e.g. GitLab) and do a pull from the server, rather than uploading and extracting a ZIP. |
39 | Extract the ZIP live on the server (control panel file managers can do this, or a simple custom PHP script) |
Code (PHP)<?php /*
Composr Copyright (c) Christopher Graham, 2004-2024 See docs/LICENSE.md for full licensing information. */ if (!isset($_GET['file'])) { exit('Need \'file\' parameter (filename to unzip)'); } $filename = $_GET['file']; error_reporting(E_ALL); ini_set('display_errors', '1'); $zip = new ZipArchive(); $res = $zip->open(dirname(__FILE__) . '/' . $filename); if ($res === true) { $zip->extractTo('.'); $zip->close(); echo 'done'; } else { echo 'failed '; switch ($res) { case ZIPARCHIVE::ER_EXISTS: echo 'ER_EXISTS'; break; case ZIPARCHIVE::ER_INCONS: echo 'ER_INCONS'; break; case ZIPARCHIVE::ER_INVAL: echo 'ER_INVAL'; break; case ZIPARCHIVE::ER_MEMORY: echo 'ER_MEMORY'; break; case ZIPARCHIVE::ER_NOENT: echo 'ER_NOENT'; break; case ZIPARCHIVE::ER_NOZIP: echo 'ER_NOZIP'; break; case ZIPARCHIVE::ER_OPEN: echo 'ER_OPEN'; break; case ZIPARCHIVE::ER_READ: echo 'ER_READ'; break; case ZIPARCHIVE::ER_SEEK: echo 'ER_SEEK'; break; } } |
40 | Run bigdump | |
41 | Delete the _temp folder and the ZIP file | |
42 | Amend _config.php live to remove your temporary details, and possibly also add a backdoor_ip line |
Code (PHP)$SITE_INFO['backdoor_ip'] = 'TODO'; Smarter configuration managementIf you want to have the exact same configuration file running across multiple machines, you can code in varying details using a switch statement…Code (PHP)switch (gethostname()) { ... } |
43 | Set file permissions on live if necessary | |
44 | Get the client to test out of the _new folder, if appropriate (in which case you'll need to temporarily set the base_url setting in _config.php) | |
45 | Move the old files on server into an _old folder | |
46 | Move files down from _new folder, changing base_url setting in _config.php back to normal if we changed it in step 44 | |
47 | Run Health Check (Admin Zone > Tools > Health Checks) | |
48 | Check for broken URLs (Admin Zone > Tools > Broken URL scanning) | |
49 | Final live testing | |
Customer interfacing
|
||
50 | Contact the website owner with whatever you need to say, including details about old files and database tables |
|
51 | Charge the website owner for the work |
See also
Feedback
Please rate this tutorial:
Have a suggestion? Report an issue on the tracker.