Webserver software – Virtual Quick Mod (vQmod) (PHP)
Informatie (ENG):
“vQmod” (aka Virtual Quick Mod) is an override system designed to avoid having to change core files. The concept is quite simple… Instead of making changes to the core files directly, the changes are created as xml search/replace script files. These script files are parsed during page load as each “source” core file is loaded with the “include” or “require” php functions. The source is then patched with the script file changes, and saved to a temp file. That temp file is then substituted for the original during execution. The original source file is never altered. This results in a “virtual” change to the core during execution without any actual modification to the core files.
See wiki links for additional information, usage, and syntax
Features
- No actual code changes are made. All changes are “virtual”, hence the name.
- Modifications are stored in their own files and applied “on-the-fly” at runtime
- Instant Single file “plug-n-play”. Add the file to apply the mod, remove the file to remove the mod.
- No worries about losing custom core changes during upgrades
- Multiple modifications can be made to the same file without conflict
- Easily update or enhance customizations without having to edit any code
- Full visual of the actual changes taking place in the generated temp files for debugging
- Fails gracefully back to the original sourcefile if there is an error
- Exceptional logging option to track every change made
- Only need to modify the index.php file to add the vQmod code one time.
- Simple structured xml format. (See readme for full breakdown of xml syntax)
- Multiple options for find/replace, regex, positions, offsets, indexing, error handling, and more!
This system can be used for any php script, forum, shopping cart, cms, etc. Anywhere custom modifications are made for reuse. The logging option is invaluable for debugging understanding exactly what is happening.
After the initial class load, the mod can actually use a script to mod itself into other core files that do the actual includes for other mods. This is the first and only known method to allow the ability to test multiple mods without actually changing files.
Who can use it?
It was initially designed in php using the OpenCart project, but it is not limited to OpenCart, nor is the concept limited to php. The class was designed to be generic enough to work with any platform. The only thing to figure is how all the include/require points of the platform so that you can make the necessary changes to install vQmod. vQmod works on an assumption that the index.php calls other controller files to load the includes, or does the includes itself. This is aimed at controller based designs (MVC, CRUD, etc). We are working on expanding from OpenCart to other platforms (phpbb, cmsmadesimple, etc)
What about performance?
Performance has been my concern from the first idea of this project. But the way the code is designed has reduced any effect on performance. We’ve got over 30 vQmod scripts on our test sites with page times and have seen absolutely no performance change when enabled or disabled. Of course any script that causes a change to db queries or has code that takes longer will be a factor but that would not be a vQmod performance issue. When the actual source files are parsed, only the files that have changes need to parse the xml scripts. Additionally, multiple performance tips and tweaks have been added as well as an optional “useCache” feature that allows you reload the changes made already from the vqcache files. All in all, performance suprisingly does not appear to be a factor at all.
Usage
1 2 3 4 5 6 |
// vQmod require_once('../vqmod/vqmod.php'); VQMod::bootup(); // VQMODDED Startup require_once(VQMod::modCheck(DIR_SYSTEM . 'startup.php')); |
Scripting
First things to set in your mind…
- The
<search>
tag can only be a single line, though doesn’t have to be a whole line, as partial matches work too. You should learn how to use the offset attribute to properly encompass all needed lines, but that doesn’t mean you should encompass many lines. Instead of trying to include many lines from top down, try starting at the bottom and finding lines going up. - Less is more! Whenever possible, try to match the smallest, yet still unique part of the code. That will improve the chances of being more future-resistant and avoid breaking other mods that may have changes close to yours.
- Pay attention to all the attribute options for each tag. There is a lot of power that is overlooked by people skimming over the syntax
How to make vQmod Scripts
There are two tools we recommend to help create vQmods if you don’t want to edit them manually
- UKSB’s vQgenerator
- AvanOsch’s vQmoderator Both are completely free and open source
vQmod currently uses an xml formatted parser by default but other parsers can be created in the future as well.
A simple replace script example looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="UTF-8"?> <modification xmlns="https://github.com/vqmod/vqmod" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://github.com/vqmod/vqmod https://raw.githubusercontent.com/vqmod/vqmod/master/vqmod.xsd" > <id>Replace 123 with ABC</id> <version>1.0.0</version> <vqmver>2.5.0</vqmver> <author>qphoria</author> <file name="relative/path/myfile.php"> <operation> <search position="replace"><![CDATA[ $var = '123'; ]]></search> <add><![CDATA[ $var = 'ABC'; ]]></add> </operation> </file> </modification> |
This script simply changes the value of a variable of “myfile.php” from “123” to “ABC” before it gets included.
Syntax
vQmod supports a number of parameters:
modification
- This is the highest level of the file and there can only be one
modification / id
- This is the name and description of the mod.
- Format: Free form text. (Informational)
modification / version
- This is the version of the mod.
- Format: Number and Decimal (1.0.0) (Informational)
modification / vqmver
- This is the minimum required version of VirtualQMod needed for the script to work.
- Format: Number and Decimal (1.0.0) (Informational)
- A required=”true” attribute can be optionally set to disable the script if it doesn’t meet the required version (Added from 2.4.0)
modification / author
- This is the author of the mod.
- Format: Free form text (Informational)
modification / file
- This is the name of the file to modify
- Requires attribute “name” as relative filename to the location of the main index.php file (e.g. catalog/controller/product/product.php). Can be delimited with commas to apply to multiple files at once (2.3.0 +) Name attribute supports a wildcard (*) character for dynamic path building. Each wildcard is limited to a single directory level.
1 2 3 |
- catalog/view/theme/*/template/product/product.tpl - catalog/view/theme/*/*/product/product.tpl - etc |
- There can be multiple file tags in a single xml file. Each file can have its own set of operations
- Optional attribute “path” can be used to prefix file name’s to avoid repetition. This is simply prepended to the file names and no validation is attempted (2.3.0 +)
- Optional attribute “error” set to log|skip|abort
- skip means it will simply ignore this file.
- log is the same as skip, but logs the error. (default)
- abort means to log the error and cancel the remaining operations in that particular xml script. It does not revert changes to other files already made in that script and doesn’t stop other xml files.
- Wildcard paths will ignore the “error” attribute completely
modification / file / operation
- This is the wrapper of the actual operation occurring.
- There can be multiple operations to the same file tag.
- Optional attribute “info” suggested. May be used by vQmod/vQmod Manager for OC in the future but at present isn’t used. This is however ideal for making files easier to read
- Optional attribute “error” set to skip|log|abort
- skip means all other operations will be applied even if one cannot. There will be no error in the log.
- log is the same as skip, but logs the error.
- abort means to log the error and revert to the original source. (default)
modification / file / operation / ignoreif
- This allows for a search to be made on a file. This search works across multiple lines not just single lines. This tag is optional and if the search is found, the operation is skipped
- Optional attribute “regex’ set to true|false. Format of data inside tag then requires delimiters for regex as it uses the standard preg_match method for php. This attribute defaults to false
modification / file / operation / search
- This is the first required step of the operation.
- Can only search single lines, both fully and partially. But offset and index attributes will assist.
- Automatically trims whitespace and linebreaks
- One
<search>
tag per<operation>
tag - Use CDATA tags to wrap code.
- Required attribute “position” set to before|after|replace|top|bottom|
all|ibefore|iafter.- replace will replace the data in the search tag with the data in the add tag. (default)
- before will insert the add data before the search data
- after will insert the add data after the search data
- top will insert the add data at the top of the file. The search data is ignored.
- bottom will insert the add data at the bottom of the file. The search data is ignored.
all will completely replace all the code in the file with the add data. The search data is ignored.Deprecated as of 2.4.0- ibefore will insert the code before the search inline instead of the line before
- iafter will insert the code afterthe search inline instead of the line before
- Optional attribute “offset” to work with the position
- if the search position is before and offset 3 it will put the add data before the line, 3 lines above the searched line
- if the search position is after and offset 3 it will put the add data after the line, 3 lines below the searched line
- if the search position is replace and offset 3 it will remove the code from the search line and the next 3 lines and replace it with the add data
- if the search position is top and offset 3 it will put the code before the line, 3 lines below the top of the file
- if the search position is bottom and offset 3 it will put the code after the line, 3 lines above the bottom of the file
- Optional attribute “index” for specifying which instances of a search tag should be acted on
- If the search string is “echo” and there are 5 echos in the file, but only want to replace the 1st and 3rd, use index=”1,3″
- Comma delimited for multiple instances starting with “1”
- Leave out or set to FALSE to replace all instances. (default)
- Optional attribute “regex” for specifying whether or not to search a regex pattern.
- If true, the search data should be a valid regex pattern
- Leave out or set to FALSE to use normal string search (default)
- Does not apply to
ibefore
andiafter
- Optional attribute “trim” set to true|false
- true will trim away whitespace and linebreaks.
- leave out or set to true to trim. (default is true)
modification / file / operation / add
- This is the second required step of the operation.
- Can be multiple lines
- One
<add>
tag per<operation>
tag. - Location of added data depends on the position attribute of the search command.
- Use CDATA tags to wrap code.
- NEW IN 2.6.0:
<add>
tag now supports all the search attributes. - Attributes in the
<add>
tag will override attributes in the<search>
tag. - Optional attribute “position” set to before|after|replace|top|bottom|ibefore|iafter.
- replace will replace the data in the search tag with the data in the add tag. (default)
- before will insert the add data before the search data
- after will insert the add data after the search data
- top will insert the add data at the top of the file. The search data is ignored.
- bottom will insert the add data at the bottom of the file. The search data is ignored.
- ibefore will insert the code before the search inline instead of the line before
- iafter will insert the code afterthe search inline instead of the line before
- Optional attribute “offset” to work with the position
- if the search position is before and offset 3 it will put the add data before the line, 3 lines above the searched line
- if the search position is after and offset 3 it will put the add data after the line, 3 lines below the searched line
- if the search position is replace and offset 3 it will remove the code from the search line and the next 3 lines and replace it with the add data
- if the search position is top and offset 3 it will put the code before the line, 3 lines below the top of the file
- if the search position is bottom and offset 3 it will put the code after the line, 3 lines above the bottom of the file
- Optional attribute “index” for specifying which instances of a search tag should be acted on
- If the search string is “echo” and there are 5 echos in the file, but only want to replace the 1st and 3rd, use index=”1,3″
- Comma delimited for multiple instances starting with “1”
- Leave out or set to FALSE to replace all instances. (default)
- Optional attribute “regex” for specifying whether or not to search a regex pattern.
- If true, the search data should be a valid regex pattern
- Leave out or set to FALSE to use normal string search (default)
- Does not apply to
ibefore
andiafter
- Optional attribute “trim” set to true|false
- true will trim away whitespace and linebreaks.
- leave out or set to true to trim. (default is true)
<![CDATA[ ]]>
- These are called CDATA tags and they are used by xml to specify that the data between should not be evaluated. It’s recommended you always use these for data between the and operation tags
[#/software/vqmod” ]