<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Zen Cart Documentation – Encapsulated Plugins</title>
    <link>https://docs.zen-cart.com/dev/plugins/encapsulated/</link>
    <description>Recent content in Encapsulated Plugins on Zen Cart Documentation</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="https://docs.zen-cart.com/dev/plugins/encapsulated/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Dev: Encapsulated Plugin Directory Structure</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/directory_structure/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/directory_structure/</guid>
      <description>
        
        
        &lt;h2 id=&#34;directory-structure&#34;&gt;Directory Structure&lt;/h2&gt;
&lt;p&gt;Plugins written for the new architecture will reside in the &lt;code&gt;zc_plugins&lt;/code&gt; directory.  Within their directory, plugin authors can add subdirectories that mimic the main Zen Cart directories. Note how each plugin starts with a versioned directory. This allows for automated upgrades and the possibility of downgrading as well.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code&gt;admin&lt;/code&gt; sub-directory &lt;em&gt;must&lt;/em&gt; be called &lt;code&gt;admin&lt;/code&gt; here (not renamed) and the &lt;code&gt;catalog&lt;/code&gt; sub-directory contains the storefront files.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zc_plugins
&lt;ul&gt;
&lt;li&gt;PluginName
&lt;ul&gt;
&lt;li&gt;v1.0.0
&lt;ul&gt;
&lt;li&gt;manifest.php&lt;/li&gt;
&lt;li&gt;database_tables.php (auto loads for both catalog and admin, since ZC v2.2.0)&lt;/li&gt;
&lt;li&gt;filenames.php (auto loads for both catalog and admin, since ZC v2.2.0)&lt;/li&gt;
&lt;li&gt;Installer
&lt;ul&gt;
&lt;li&gt;languages
&lt;ul&gt;
&lt;li&gt;english&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;admin
&lt;ul&gt;
&lt;li&gt;includes
&lt;ul&gt;
&lt;li&gt;auto_loaders&lt;/li&gt;
&lt;li&gt;classes
&lt;ul&gt;
&lt;li&gt;observers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;extra_configures&lt;/li&gt;
&lt;li&gt;extra_datafiles&lt;/li&gt;
&lt;li&gt;functions
&lt;ul&gt;
&lt;li&gt;extra_functions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;init_includes&lt;/li&gt;
&lt;li&gt;javascript&lt;/li&gt;
&lt;li&gt;languages
&lt;ul&gt;
&lt;li&gt;english
&lt;ul&gt;
&lt;li&gt;extra_definitions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;catalog
&lt;ul&gt;
&lt;li&gt;includes
&lt;ul&gt;
&lt;li&gt;auto_loaders&lt;/li&gt;
&lt;li&gt;classes
&lt;ul&gt;
&lt;li&gt;ajax&lt;/li&gt;
&lt;li&gt;observers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;extra_configures&lt;/li&gt;
&lt;li&gt;extra_datafiles&lt;/li&gt;
&lt;li&gt;functions
&lt;ul&gt;
&lt;li&gt;extra_functions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;init_includes&lt;/li&gt;
&lt;li&gt;languages
&lt;ul&gt;
&lt;li&gt;english
&lt;ul&gt;
&lt;li&gt;extra_definitions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;modules
&lt;ul&gt;
&lt;li&gt;pages&lt;/li&gt;
&lt;li&gt;sideboxes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;templates
&lt;ul&gt;
&lt;li&gt;default
&lt;ul&gt;
&lt;li&gt;common (note that only &lt;em&gt;additional&lt;/em&gt; common files will be loaded!)&lt;/li&gt;
&lt;li&gt;css&lt;/li&gt;
&lt;li&gt;images&lt;/li&gt;
&lt;li&gt;jscript&lt;/li&gt;
&lt;li&gt;templates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;v1.0.1
&lt;ul&gt;
&lt;li&gt;Uses a similar structure to v1.0.0, with any files added/modified/removed since that version&lt;/li&gt;
&lt;li&gt;EVERY subsequent version MUST BE able to exist on its own without any prior versions installed. ie: must be a complete fileset.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Zen Cart v1.5.7 or later is required. Plugins for prior versions must be installed directly into the main Zen Cart directory structure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;Installer&lt;/code&gt; folder is optional; you can embed the installation logic in your plugin if you prefer.  See &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/&#34;&gt;Installer Classes&lt;/a&gt; and &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/sql_installation/&#34;&gt;Plugin SQL Installation&lt;/a&gt; for details on using the &lt;code&gt;Installer&lt;/code&gt; folder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Naming an &lt;code&gt;/admin/javascript/&lt;/code&gt; file the same name as your PHP file name will make it automatically load.  If you have additional .js files to load, give them names starting with the PHP file name followed by an underscore.  For example, if you create a file called &lt;code&gt;admin/rewards.php&lt;/code&gt;, the autoloader will load &lt;code&gt;admin/includes/javascript/rewards.js&lt;/code&gt;, as well as any JavaScript file whose name matches the pattern &lt;code&gt;admin/includes/javascript/rewards_*.js&lt;/code&gt;, e.g. &lt;code&gt;admin/includes/javascript/rewards_sha-256.js&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Encapsulated Plugin Manifest Files</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/manifests/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/manifests/</guid>
      <description>
        
        
        &lt;h2 id=&#34;manifest-files&#34;&gt;Manifest Files&lt;/h2&gt;
&lt;p&gt;Each plugin must have a &lt;code&gt;manifest.php&lt;/code&gt; file in the root of its version directory.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zc_plugins
&lt;ul&gt;
&lt;li&gt;myPlugin
&lt;ul&gt;
&lt;li&gt;v1.0.0
&lt;ul&gt;
&lt;li&gt;manifest.php&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example manifest file would look like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;lt;?php
return [
    &amp;#39;pluginVersion&amp;#39; =&amp;gt; &amp;#39;v3.0.0&amp;#39;,
    &amp;#39;pluginName&amp;#39; =&amp;gt; &amp;#39;Display logs&amp;#39;,
    &amp;#39;pluginDescription&amp;#39; =&amp;gt; &amp;#39;Display and manage Zen Cart log files.&amp;#39;,
    &amp;#39;pluginAuthor&amp;#39; =&amp;gt; &amp;#39;Vinos de Frutas Tropicales (lat9)&amp;#39;,
    &amp;#39;pluginId&amp;#39; =&amp;gt; 1583, // ID from Zen Cart forum
    &amp;#39;zcVersions&amp;#39; =&amp;gt; [&amp;#39;v157&amp;#39;],
    &amp;#39;changelog&amp;#39; =&amp;gt; &amp;#39;&amp;#39;, // online URL (eg github release tag page, or changelog file there) or local filename only, ie: changelog.txt (in same dir as this manifest file)
    &amp;#39;github_repo&amp;#39; =&amp;gt; &amp;#39;&amp;#39;, // url
    &amp;#39;pluginGroups&amp;#39; =&amp;gt; [],
];
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;pluginversion&#34;&gt;pluginVersion&lt;/h3&gt;
&lt;p&gt;The version of this plugin. It should match the version number entered when submitting the plugin to the Plugins Library on the Zen Cart forum.&lt;/p&gt;
&lt;h3 id=&#34;pluginname&#34;&gt;pluginName&lt;/h3&gt;
&lt;p&gt;A human readable string for the name of the plugin.&lt;/p&gt;
&lt;h3 id=&#34;plugindescription&#34;&gt;pluginDescription&lt;/h3&gt;
&lt;p&gt;A human readable string describing the plugin.&lt;/p&gt;
&lt;p&gt;Flagrant advertising is not permitted.&lt;/p&gt;
&lt;h3 id=&#34;pluginauthor&#34;&gt;pluginAuthor&lt;/h3&gt;
&lt;p&gt;A human readable string for the plugin author.&lt;/p&gt;
&lt;h3 id=&#34;pluginid&#34;&gt;PluginId&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; number assigned by the Zen Cart forum site when submitting the plugin for review, e.g. &lt;a href=&#34;https://www.zen-cart.com/downloads.php?do=file&amp;amp;id=1583&#34;&gt;https://www.zen-cart.com/downloads.php?do=file&amp;amp;id=1583&lt;/a&gt;. This is used by the store&amp;rsquo;s Plugin Manager to check for whether new versions have been submitted.&lt;/p&gt;
&lt;p&gt;The Plugin Manager only alerts about new versions of this plugin if the store&amp;rsquo;s Zen Cart version matches one of the versions specified in a given update on the Zen Cart Plugins Library.  Set it to &lt;code&gt;0&lt;/code&gt; if you&amp;rsquo;re writing a plugin that you&amp;rsquo;re not submitting to the Plugins Library. (eg: a commercial plugin)&lt;/p&gt;
&lt;h3 id=&#34;changelog&#34;&gt;changelog&lt;/h3&gt;
&lt;p&gt;Online URL (eg github release tag page, or changelog file there) or local filename only, ie: changelog.txt (in same dir as this manifest file)&lt;/p&gt;
&lt;h3 id=&#34;github_repo&#34;&gt;github_repo&lt;/h3&gt;
&lt;p&gt;A link to the plugin&amp;rsquo;s github repo, if one exists.&lt;/p&gt;
&lt;h3 id=&#34;zcversions&#34;&gt;zcVersions&lt;/h3&gt;
&lt;p&gt;An array of the Zen Cart versions the plugin supports. (eg: &lt;code&gt;[&#39;v157&#39;]&lt;/code&gt;, or &lt;code&gt;[&#39;v157&#39;,&#39;v158&#39;]&lt;/code&gt;). Note the &lt;code&gt;v&lt;/code&gt; prefix and the 3 digits and the lack of decimals (&amp;quot;&lt;code&gt;.&lt;/code&gt;&amp;quot;).&lt;/p&gt;
&lt;h3 id=&#34;plugingroups&#34;&gt;pluginGroups&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;not currently supported&lt;/code&gt; but will eventually support filtering the display of plugins in the admin.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Encapsulated Plugin Installer Language Files</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/plugin_language_files/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/plugin_language_files/</guid>
      <description>
        
        
        &lt;h2 id=&#34;plugin-installer-language-files&#34;&gt;Plugin Installer Language Files&lt;/h2&gt;
&lt;p&gt;While most language constants for the plugin installer are managed internally there will be cases where a plugin needs to define some of its own language defines.&lt;/p&gt;
&lt;p&gt;For example, if the plugin needs to test some pre-requisites before installing, the error messages for when those
pre-requisites fail will need to be defined.  In these cases the plugin system allows for loading custom language files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; These files use &lt;code&gt;define()&lt;/code&gt; statements. The array-based language-file format is not supported here.&lt;/p&gt;
&lt;p&gt;The main custom language file would reside in the &lt;code&gt;[plugin version directory]/languages/[language name]/main.php&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;zc_plugins&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PluginName&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;v1.0.0&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Installer&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;languages&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;english&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main.php&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the plugin needs more customization and wants to split off other language defines into separate files it can also load the language files separately. A helper method in the installer class can be used to do this.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$this-&amp;gt;loadInstallerLanguageFile(&#39;myFile.php&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember, we are talking here about language defines that are &lt;em&gt;only used during installation&lt;/em&gt;. Loading of language files needed by the plugin itself are handled differently.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Encapsulated Plugin Installer Classes</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/</guid>
      <description>
        
        
        &lt;h2 id=&#34;installer-classes&#34;&gt;Installer Classes&lt;/h2&gt;
&lt;p&gt;In many cases you may not need anything custom done for a plugin beyond merely some SQL queries, which would be done in &lt;code&gt;install.sql&lt;/code&gt; and removed via &lt;code&gt;uninstall.sql&lt;/code&gt;. (But upgrades cannot be done merely via &lt;code&gt;.sql&lt;/code&gt; files.)&lt;/p&gt;
&lt;p&gt;However there may be times when a plugin needs to override the default installer behavior. Or handle database-changes during an Upgrade from a prior plugin version.&lt;/p&gt;
&lt;p&gt;For example a plugin may need to check some pre-requisites before allowing installation, such as the availability of a PHP extension or maybe the plugin relies on another plugin being installed.&lt;/p&gt;
&lt;p&gt;In these cases the plugin can define its own installer class that extends the base installer.&lt;/p&gt;
&lt;p&gt;The class must be named &lt;code&gt;ScriptedInstaller.php&lt;/code&gt; and be placed in the &lt;code&gt;Installer&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;e.g.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;zc_plugins&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;rewardPoints&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;v1.0.0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Installer&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ScriptedInstaller.php&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The skeleton of this class should look like :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
use Zencart\PluginSupport\ScriptedInstaller as ScriptedInstallBase;

class ScriptedInstaller extends ScriptedInstallBase
{ 
    /**
     * @return bool
     */
    protected function executeInstall()
    {
        return true;
    }

    /**
     * @return bool
     */
    protected function executeUninstall()
    {
        return true;
    }

    /**
     * @return bool
     */
    protected function executeUpgrade($oldVersion)
    {
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;important-notes-for-coding-in-the-context-of-a-scriptedinstaller-class&#34;&gt;Important Notes for coding in the context of a &lt;code&gt;ScriptedInstaller&lt;/code&gt; class&lt;/h3&gt;
&lt;h4 id=&#34;database-querying&#34;&gt;Database Querying&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Using the alternate query functions below will allow the ScriptedInstaller to report query failures so that the install aborts with a logged and displayed message.&lt;/li&gt;
&lt;li&gt;Avoid making &lt;code&gt;$db-&amp;gt;&lt;/code&gt; calls directly (tip: if you have to &lt;code&gt;global $db&lt;/code&gt; then you&amp;rsquo;re not doing it right! &amp;hellip; in this context.&lt;/li&gt;
&lt;li&gt;For non-SELECT queries, instead of &lt;code&gt;$db-&amp;gt;Execute($sql)&lt;/code&gt; use &lt;code&gt;$this-&amp;gt;executeInstallerSql($sql)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For a SELECT query use &lt;code&gt;$this-&amp;gt;executeInstallerSelectQuery($sql)&lt;/code&gt; instead of &lt;code&gt;$db-&amp;gt;Execute($sql)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Instead of &lt;code&gt;zen_db_perform()&lt;/code&gt; use &lt;code&gt;$this-&amp;gt;executeInstallerDbPerform()&lt;/code&gt; with the same usual parameters.&lt;/li&gt;
&lt;li&gt;The record ID of a single record created by a db query can be accessed with &lt;code&gt;$insert_id = $this-&amp;gt;dbConn-&amp;gt;insert_ID();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The number of rows affected by a query can be accessed with &lt;code&gt;$rows = $this-&amp;gt;dbConn-&amp;gt;affectedRows();&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;$this-&amp;gt;dbConn-&amp;gt;&lt;/code&gt; instead of &lt;code&gt;$db-&amp;gt;&lt;/code&gt; if you really need to access the &lt;code&gt;queryFactory&lt;/code&gt; object directly.&lt;/li&gt;
&lt;li&gt;If you need to inspect the database schema, use the &lt;code&gt;global $sniffer&lt;/code&gt; class, as you normally would.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;database-defines&#34;&gt;Database DEFINES&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;NEW database TABLES need to have constants defined!!!!
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/catalog/includes/extra_datafiles/database_tables.php&lt;/code&gt; if you need to use the table catalog-side&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/admin/includes/extra_datafiles/database_tables.php&lt;/code&gt; if you need to use the table admin-side&lt;/li&gt;
&lt;li&gt;and inside your &lt;code&gt;ScriptedInstaller.php&lt;/code&gt;, at the top of the class or at least before you use the constant&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;configuration-and-configuration_group-records&#34;&gt;Configuration and Configuration_Group records&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Many helper functions for &lt;code&gt;configuration&lt;/code&gt; and &lt;code&gt;configuration_group&lt;/code&gt; tables are shown in the example template below&lt;/li&gt;
&lt;li&gt;Consult &lt;code&gt;/includes/classes/PluginSupport/ScriptedInstallHelpers.php&lt;/code&gt; for more insight on the many helper functions available&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;handling-errors&#34;&gt;Handling Errors&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;ERROR messages may be triggered via &lt;code&gt;$this-&amp;gt;errorContainer-&amp;gt;addError(0, &#39;message to log&#39;, false, &#39;message to show to user&#39;);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If errors are added to &lt;code&gt;errorContainer&lt;/code&gt;, then no matter how much progress was done, the errors will be displayed in the messageStack and the plugin version will NOT be marked as installed/upgraded.&lt;/li&gt;
&lt;li&gt;It is best to &lt;code&gt;return false;&lt;/code&gt; immediately after you trigger an error so that no further processing is done; else it will keep going and more errors will be collected.&lt;/li&gt;
&lt;li&gt;When returning from &lt;code&gt;executeInstall()&lt;/code&gt;, &lt;code&gt;executeUninstall()&lt;/code&gt;, and &lt;code&gt;executeUpgrade()&lt;/code&gt;, returning &lt;code&gt;false&lt;/code&gt; or triggering an error will abort and not mark it installed. If no errors are set and &lt;code&gt;true&lt;/code&gt; is returned, the plugin will be marked as installed (or if upgrading, the new version will be set as the active one).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;building-upgrades-from-prior-versions&#34;&gt;Building Upgrades From Prior Versions&lt;/h4&gt;
&lt;p&gt;When building upgrades in &lt;code&gt;ScriptedInstaller&lt;/code&gt; remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;executeInstall()&lt;/code&gt; is for NEW installs, so should also include anything that an upgrade from previous version would do&lt;/li&gt;
&lt;li&gt;&lt;code&gt;executeUninstall()&lt;/code&gt; is to remove ALL changes for the plugin even after multiple upgrades (you might choose to NOT drop columns from db, to avoid user-error by accidental uninstall of the plugin)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;executeUpgrade()&lt;/code&gt; should include ALL upgrades from ALL prior versions, since users can skip a version and therefore you need to cover all scenarios&lt;/li&gt;
&lt;li&gt;While &lt;code&gt;executeUpgrade($oldVersion)&lt;/code&gt; provides the version from which the upgrade is being done, it is better to code assuming none of any upgrades are done, by checking and performing all updates that would be needed to get any version up-to-date.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;informational-properties&#34;&gt;Informational Properties&lt;/h4&gt;
&lt;p&gt;A few properties exist to assist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$this-&amp;gt;pluginDir&lt;/code&gt; refers to the parent directory of the version you&amp;rsquo;re currently working in.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$this-&amp;gt;pluginKey&lt;/code&gt; is the name of the plugin&amp;rsquo;s database key identifier.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$this-&amp;gt;version&lt;/code&gt; is the version you&amp;rsquo;re currently &amp;ldquo;in&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$this-&amp;gt;oldVersion&lt;/code&gt;, which is only available when upgrading (otherwise null), indicates the version being upgraded from.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;example-scriptedinstaller-template&#34;&gt;Example &lt;code&gt;ScriptedInstaller&lt;/code&gt; Template&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Zencart\PluginSupport\ScriptedInstaller&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;ScriptedInstallBase&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;ScriptedInstaller&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;ScriptedInstallBase&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     * @return bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;executeInstall&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// check whether the PHP version has the required features // using mb_strtolower just as an example here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;function_exists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;mb_strtolower&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// trigger an error, which will cause the plugin to NOT get marked as installed, AND will display the error message
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;errorContainer&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;addError&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;error message for the log file&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;error message for display to the user (do not include sensitive details here)&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// return now to abort the rest of the installation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// probably important to de-register the page key if you&amp;#39;re converting an old plugin and using the same key name, so the new details are correct
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;zen_page_key_exists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;myAdminPageKey&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;zen_deregister_admin_pages&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;([&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;myAdminPageKey&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// check if the key exists first, because re-registering will trigger errors
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;zen_page_key_exists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;myAdminPageKey&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;zen_register_admin_page&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;myAdminPageKey&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;language_key&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;main_page&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;page_params&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;menu_key&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;display_on_menuYN&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;sort_order_int&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// read a configuration key value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$cKey&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;getConfigurationKeyDetails&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;MY_MOD_SOMETHING&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// create a new configuration group // NOTE: YOU PROBABLY DON&amp;#39;T NEED A NEW GROUP, but this is an easy way to create one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$groupId&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;addConfigurationGroup&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;([&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_group_title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Name up to 64 characters&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_group_description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Description up to 255 chars&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;sort_order&amp;#39; =&amp;gt; 0, // int (will be made to match auto-increment id if not specified)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;visible&amp;#39; =&amp;gt; 1, // 0 or 1, default &amp;#39;1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// register a configuration key
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;addConfigurationKey&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;MY_MOD_MAX_ROWS_DISPLAY&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_title&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Display Maximum Rows&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_value&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;20&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_description&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Identify the maximum number of records to display.  (Default: &amp;lt;b&amp;gt;20&amp;lt;/b&amp;gt;)&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;configuration_group_id&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// could use a variable to indicate a group ID here, such as $groupId from the above example
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;sort_order&amp;#39; =&amp;gt; 100, // INT(5) default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;use_function&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;set_function&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;val_function&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// DATABASE CHANGES
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/** @var sniffer $sniffer */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;global&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$sniffer&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000&#34;&gt;define&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;TABLE_MY_NEW_TABLE&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;DB_PREFIX&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;my_new_table&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// NOTE: Be sure to ALSO add any database table constant defines to the admin and/or catalog extra_datafiles directory.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// Add a Table:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sniffer&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;table_exists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;some_certain_field&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!==&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;CREATE TABLE IF NOT EXISTS &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34; (
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;                id INT NOT NULL auto_increment,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;                name varchar(32) default NULL,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;                PRIMARY KEY (id),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;                KEY idx_mynewtable_name (name)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;            )&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;executeInstallerSql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// Add a Field:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sniffer&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;field_exists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;some_certain_field&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;ALTER TABLE &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34; ADD some_certain_field TINYINT NOT NULL DEFAULT 0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;executeInstallerSql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// Add an index:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sniffer&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;indexExists&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;idx_certain_field&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;ALTER TABLE &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;TABLE_MY_NEW_TABLE&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34; ADD INDEX idx_certain_field (some_certain_field)&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;executeInstallerSql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$sql&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// or false on failure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     * @return bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;executeUninstall&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000&#34;&gt;zen_deregister_admin_pages&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;([&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;yourPageKeyNameHere&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;deleteConfigurationGroup&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$groupName&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$boolWhetherToDeleteAllConfigKeysInThisGroup&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;deleteConfigurationKeys&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$arrayOfKeyNames&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// or false on failure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     * @return bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;executeUpgrade&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$oldVersion&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// get a configuration group ID, and optionally create it if it doesn&amp;#39;t already exist
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$groupId&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;getOrCreateConfigGroupId&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;My Group Name&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;description&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// maybe update the title or description of the group?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$changed&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;updateConfigurationGroup&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$groupId&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;configuration_group_title&amp;#39; =&amp;gt; &amp;#39;something&amp;#39;, // varchar(64) NOT NULL default &amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;configuration_group_description&amp;#39; =&amp;gt; &amp;#39;something&amp;#39;, // varchar(255) NOT NULL default &amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;sort_order&amp;#39; =&amp;gt; 0, // int(5) default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;//&amp;#39;visible&amp;#39; =&amp;gt; 1, // int(1) default &amp;#39;1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// maybe update parts of a configuration table record, passing only the fields that need updating for this version
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000&#34;&gt;$cID&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$this&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;updateConfigurationKey&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;MY_MOD_SOMETHING&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;configuration_title&amp;#39; =&amp;gt; &amp;#39;something&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;configuration_value&amp;#39; =&amp;gt; &amp;#39;something&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;configuration_description&amp;#39; =&amp;gt; &amp;#39;something&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;configuration_group_id&amp;#39; =&amp;gt; $groupId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;sort_order&amp;#39; =&amp;gt; &amp;#39;some_int&amp;#39;, // INT(5) default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;use_function&amp;#39; =&amp;gt; &amp;#39;&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;set_function&amp;#39; =&amp;gt; &amp;#39;&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// &amp;#39;val_function&amp;#39; =&amp;gt; &amp;#39;&amp;#39;, // TEXT default NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// or false on failure
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
      </description>
    </item>
    
    <item>
      <title>Dev: Encapsulated Plugin Class Autoloading</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/class_autoloading/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/class_autoloading/</guid>
      <description>
        
        
        &lt;h2 id=&#34;class-autoloading&#34;&gt;Class Autoloading&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;Class Autoloading&lt;/em&gt;&amp;rdquo; means: &amp;ldquo;when I want to use a class, I simply attempt to instantiate it (ie: &lt;code&gt;new Foo()&lt;/code&gt;) and PHP will automatically find the right file, load it (so I don&amp;rsquo;t have to &lt;code&gt;include()&lt;/code&gt; or &lt;code&gt;require()&lt;/code&gt; it manually), and then do the requested creation of an instance of it&amp;rdquo;. In most cases this is the best way.&lt;/p&gt;
&lt;p&gt;Encapsulated plugins allow you to Autoload classes based on 2 scenarios.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where the class follows PSR4 and the filename is the same as the class name (This is the best way). Naming should be CamelCased.&lt;/li&gt;
&lt;li&gt;Where the filename is different to the class name (This should be rare).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;psr4-based-classes&#34;&gt;PSR4 based classes&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Formula for catalog:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;place your class in the plugin&amp;rsquo;s &lt;code&gt;[version]/catalog/includes/classes/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;name the class and its filename the same (ie: &lt;code&gt;catalog/includes/classes/DrawPrettyGraph.php&lt;/code&gt; should contain a class named &lt;code&gt;DrawPrettyGraph&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;set the &lt;code&gt;namespace&lt;/code&gt;: &lt;code&gt;namespace Zencart\Plugins\Catalog\SalesGraphs;&lt;/code&gt; if the plugin&amp;rsquo;s name is &lt;code&gt;Sales Graphs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Formula for admin:&lt;/strong&gt; (basically, change &amp;ldquo;catalog&amp;rdquo; to &amp;ldquo;admin&amp;rdquo; for directory name and namespace)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;place your class in the plugin&amp;rsquo;s &lt;code&gt;[version]/admin/includes/classes/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;name the class and its filename the same (ie: &lt;code&gt;admin/includes/classes/DrawPrettyGraph.php&lt;/code&gt; should contain a class named &lt;code&gt;DrawPrettyGraph&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;set the &lt;code&gt;namespace&lt;/code&gt;: &lt;code&gt;namespace Zencart\Plugins\Admin\SalesGraphs;&lt;/code&gt; if the plugin&amp;rsquo;s name is &lt;code&gt;Sales Graphs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;example-for-a-plugin-named-sales-graphs&#34;&gt;Example, for a plugin named &lt;code&gt;Sales Graphs&lt;/code&gt;:&lt;/h3&gt;
&lt;h4 id=&#34;filename&#34;&gt;Filename&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;zc_plugins/SalesGraphs/vX.Y/admin/includes/classes/DrawPrettyGraph.php&lt;/code&gt;&lt;/p&gt;
&lt;h4 id=&#34;contents&#34;&gt;Contents&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;namespace&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Zencart\Plugins\Admin\DisplayLogs&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;DrawPrettyGraph&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;output&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Look at my pretty graph!&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;invoking&#34;&gt;Invoking&lt;/h4&gt;
&lt;p&gt;now in any file you can invoke it directly:
&lt;code&gt;$myGraph = (new ZenCart\Plugins\Admin\SalesGraphs\DrawPrettyGraph)-&amp;gt;output();&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or if you&amp;rsquo;d like to split the namespace out separately to make lines shorter, use 2 steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At the top of whatever file you wish to use it, add a line: &lt;code&gt;use Zencart\Plugins\Admin\SalesGraphs\DrawPrettyGraph;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then call it: &lt;code&gt;$myGraph = (new DrawPrettyGraph)-&amp;gt;output();&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;custom-class-filenames&#34;&gt;Custom class filenames&lt;/h2&gt;
&lt;p&gt;When the filename of a class does not match the class name, we need to do a bit more work.&lt;/p&gt;
&lt;p&gt;The best situation is to avoid using custom class filenames, and to follow the standards provided above. Your IDE/editor will also be happier in such cases as well.&lt;/p&gt;
&lt;p&gt;From the example above, if we had a class filename of &lt;code&gt;class.some_weird_class_filename.php&lt;/code&gt; and the class name was &lt;code&gt;myClass&lt;/code&gt;, then we would have to set up autoloading manually at tthe top of whatever file needs it. The following would need to be called after the line
&lt;code&gt;require &#39;includes/application_top.php&#39;;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$psr4Autoloader&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;setClassFile&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Zencart\Plugins\Admin\SalesGraphs\myClass&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$filePathPluginAdmin&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;SalesGraphs&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;class.some_weird_class_filename.php&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$myClass&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Zencart\Plugins\Admin\SalesGraphs\myClass&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$myClass&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;output&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This would output &lt;code&gt;&#39;Look at my pretty graph!&#39;&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Encapsulated Plugin SQL Installation</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/sql_installation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/sql_installation/</guid>
      <description>
        
        
        &lt;p&gt;Plugins might need to create/alter database tables and/or insert/amend data in database tables.&lt;/p&gt;
&lt;p&gt;The plugin installer allows two methods for doing this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A class-based approach where each database alteration is done with PHP code. This approach also allows for upgrading between versions when you release updates.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;.sql&lt;/code&gt; files containing just SQL statements. This should only be used in VERY simple scenarios, where upgrades will never be needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;sql-installer-classes&#34;&gt;SQL Installer Classes&lt;/h2&gt;
&lt;p&gt;If you have more complex needs when creating schemas or seeding the database, instead of using a plain SQL install file as above, you can use a class based method, by extending ScriptedInstallBase as &lt;code&gt;/Installer/ScriptedInstaller.php&lt;/code&gt; in your plugin. See &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/&#34;&gt;Installer Classes&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;IF YOUR PLUGIN PROVIDES UPGRADES WHICH NEED DATABASE CHANGES, then you MUST use the &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/&#34;&gt;Installer Classes&lt;/a&gt;, since there is no way to offer plain &lt;code&gt;.sql&lt;/code&gt; file upgrades.&lt;/p&gt;
&lt;p&gt;An example is provided in the &lt;code&gt;DisplayLogs&lt;/code&gt; plugin, in &lt;code&gt;zc_plugins/DisplayLogs/[version]/Installer/ScriptedInstaller.php&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Briefly, three key methods that must be implemented in a class which extends &lt;code&gt;ScriptedInstallBase&lt;/code&gt; are &lt;code&gt;executeInstall&lt;/code&gt; and &lt;code&gt;executeUninstall&lt;/code&gt; and &lt;code&gt;executeUpgrade&lt;/code&gt;, which run the installation, de-installation and upgrade logic, respectively. They should return &lt;code&gt;true&lt;/code&gt; on success, and &lt;code&gt;false&lt;/code&gt; on failure. They can set &lt;code&gt;$this-&amp;gt;errorContainer-&amp;gt;addError($severity=0, $logMessage, $booleanShowLogToUser, $userMessage)&lt;/code&gt; if any errors need to be logged and/or shown to the user.&lt;/p&gt;
&lt;h2 id=&#34;plain-sql-files&#34;&gt;Plain SQL Files&lt;/h2&gt;
&lt;p&gt;If your needs are VERY simple, and upgrades will never be necessary, you could use just a plain .sql file:&lt;/p&gt;
&lt;p&gt;Create a plain SQL file called &lt;code&gt;install.sql&lt;/code&gt; with the SQL statements you need for installation. Be sure to make your installation robust in the face of prior partial or failed installs (e.g. use &lt;code&gt;IF NOT EXISTS&lt;/code&gt;, &lt;code&gt;INSERT IGNORE&lt;/code&gt; and so forth).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE TABLE IF NOT EXISTS reward_master (
                           rewards_products_id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
                           scope INT( 1 ) NOT NULL DEFAULT &#39;0&#39;,
                           scope_id INT( 11 ) NOT NULL DEFAULT &#39;0&#39;,
                           point_ratio DOUBLE( 15, 4 ) NOT NULL DEFAULT &#39;1&#39;,
                           bonus_points DOUBLE( 15, 4 ) NULL,
                           redeem_ratio DOUBLE( 15, 4 ) NULL,
                           redeem_points DOUBLE( 15, 4 ) NULL,
                           UNIQUE unique_id ( scope , scope_id ));

INSERT IGNORE INTO reward_master
(rewards_products_id ,scope ,scope_id ,point_ratio ,bonus_points, redeem_ratio, redeem_points)
VALUES (NULL , &#39;0&#39;, &#39;0&#39;, &#39;1.0000&#39;, NULL, 0.01, NULL);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sql file should reside in&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;zc_plugins&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PluginName&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;v1.0.0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Installer&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;install.sql&lt;/li&gt;
&lt;li&gt;uninstall.sql&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt; With this &lt;code&gt;install.sql&lt;/code&gt; approach, there is no way to safely roll back any installer SQL if an error occurs.&lt;/p&gt;
&lt;p&gt;Note that an uninstall script (called &lt;code&gt;uninstall.sql&lt;/code&gt;) may be placed in the same folder.&lt;/p&gt;
&lt;h3 id=&#34;currently-supported-sql-commands&#34;&gt;Currently Supported SQL Commands&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;DROP TABLE IF EXISTS &amp;lt;table name&amp;gt;;&lt;/li&gt;
&lt;li&gt;DROP TABLE &amp;lt;table name&amp;gt;;&lt;/li&gt;
&lt;li&gt;CREATE TABLE IF NOT EXISTS &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;CREATE TABLE &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;TRUNCATE TABLE &amp;lt;table name&amp;gt;;&lt;/li&gt;
&lt;li&gt;REPLACE INTO &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;INSERT INTO  &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;INSERT IGNORE INTO &amp;lt;table name&amp;gt; &lt;additional sql&gt;;&lt;/li&gt;
&lt;li&gt;ALTER TABLE &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;RENAME TABLE &amp;lt;table name&amp;gt; TO &amp;lt;table name&amp;gt;;&lt;/li&gt;
&lt;li&gt;UPDATE &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;DELETE FROM &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;DROP INDEX &amp;lt;index name&amp;gt; ON &amp;lt;table name&amp;gt;;&lt;/li&gt;
&lt;li&gt;CREATE INDEX &amp;lt;index name&amp;gt; ON &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;SELECT &amp;lt;fields&amp;gt; FROM &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;;&lt;/li&gt;
&lt;li&gt;SELECT &amp;lt;fields&amp;gt; FROM &amp;lt;table name&amp;gt; &amp;lt;join type&amp;gt; JOIN &amp;lt;table name&amp;gt; &amp;lt;additional sql&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;lt;table name&amp;gt; is the name of the table(s) which may require a suffix adding&lt;/li&gt;
&lt;li&gt;&amp;lt;additional sql&amp;gt; is additional valid sql for the statement. &lt;strong&gt;It must not contain any table names that may require prefixing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;index name&amp;gt; is the name of the index to be created/dropped&lt;/li&gt;
&lt;li&gt;&amp;lt;join type&amp;gt; is the type  INNER, OUTER, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There must be exactly one space before &amp;lt;table name&amp;gt;.&lt;/li&gt;
&lt;li&gt;The statement before the first &amp;lt; must be single spaced.&lt;/li&gt;
&lt;li&gt;There can be multiple JOIN statements in a select.&lt;/li&gt;
&lt;li&gt;Every statement must end with a semi-colon (&lt;code&gt;;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Sub selects are not available.&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Converting a Plugin to the Encapsulated Architecture</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/converting/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/converting/</guid>
      <description>
        
        
        &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; For simplicity, files like &lt;code&gt;license.txt&lt;/code&gt;, &lt;code&gt;README.txt&lt;/code&gt; and &lt;code&gt;docs&lt;/code&gt; are omitted; no changes are made to those files, which are not deployed.&lt;/p&gt;
&lt;p&gt;Converting an older plugin to use the encapsulated architecture can be done
following these steps:&lt;/p&gt;
&lt;h3 id=&#34;1-create-the-plugins-file-hierarchy&#34;&gt;1. Create the plugin&amp;rsquo;s file hierarchy.&lt;/h3&gt;
&lt;p&gt;As a general rule, this just means moving the files you currently have in the plugin&amp;rsquo;s top level folder under a new folder with the name &lt;code&gt;Plugin Name/Version&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, the &lt;a href=&#34;https://www.zen-cart.com/downloads.php?do=file&amp;amp;id=2039&#34;&gt;Mod List&lt;/a&gt; files, prior to conversion, were:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./admin/includes/languages/english/extra_definitions/mod_list.php
./admin/includes/languages/english/mod_list.php
./admin/includes/extra_configures/mod_list.php
./admin/mod_list.php
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; On a live system the admin folder will have been renamed.&lt;/p&gt;
&lt;p&gt;These become:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.0/admin/includes/languages/english/extra_definitions/mod_list.php
./zc_plugins/ModList/1.4.0/admin/includes/languages/english/mod_list.php
./zc_plugins/ModList/1.4.0/admin/includes/extra_configures/mod_list.php
./zc_plugins/ModList/1.4.0/admin/mod_list.php
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; It is not necessary to rename admin in the plugin directory hierarchy&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;For Zen Cart versions 2.1.0 and later, only array-based language files are supported for encapsulated plugins&lt;/strong&gt;&lt;/em&gt;.  Using the example above, the admin folder&amp;rsquo;s files will be&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.0/admin/includes/languages/english/extra_definitions/lang.mod_list.php
./zc_plugins/ModList/1.4.0/admin/includes/languages/english/lang.mod_list.php
./zc_plugins/ModList/1.4.0/admin/includes/extra_configures/mod_list.php
./zc_plugins/ModList/1.4.0/admin/mod_list.php
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;2-add-the-manifest&#34;&gt;2. Add the Manifest&lt;/h3&gt;
&lt;p&gt;Create a &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/manifests/&#34;&gt;manifest file&lt;/a&gt;. In our example, this will be placed in&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.0/manifest.php
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;3-add-the-plugin-installer-script&#34;&gt;3. Add the Plugin Installer script&lt;/h3&gt;
&lt;p&gt;Create an &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/installer_classes/&#34;&gt;installer script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our example, this will be placed in&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.0/Installer/PluginInstaller.php
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;4-optional-create-install-and-uninstall-files&#34;&gt;4. (optional) Create install and uninstall files&lt;/h3&gt;
&lt;p&gt;If the installer script you created above did not do the SQL operations
required by the plugin, you can use &lt;a href=&#34;https://docs.zen-cart.com/dev/plugins/encapsulated/sql_installation/&#34;&gt;plain SQL files&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our example, these will be placed in&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.0/Installer/uninstall.sql
./zc_plugins/ModList/1.4.0/Installer/install.sql
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;5-remove-old-files-and-update-documentation&#34;&gt;5. Remove old files and update documentation&lt;/h3&gt;
&lt;p&gt;Once you have put your the &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;includes&lt;/code&gt;, etc. folders under &lt;code&gt;zc_plugins&lt;/code&gt;, &lt;em&gt;do not&lt;/em&gt; duplicate them at the top level for older versions of Zen Cart.
Instead, update the README file for your plugin with guidance like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;If you are running a  Zen Cart installation older than 1.5.7, do not copy in the `zc_plugins` folder.  Instead, 
go to the `zc_plugins/YOURPLUGIN/VERSION/` folder and copy the `admin` and `includes` folders to your shopping cart (after renaming the `admin` folder.)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alternately, you may mark your plugin as &amp;ldquo;1.5.7 (and above) only.&amp;rdquo;&lt;/p&gt;
&lt;h3 id=&#34;6-final-result&#34;&gt;6. Final Result&lt;/h3&gt;
&lt;p&gt;Now the file hierarchy looks  like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;./zc_plugins/ModList/1.4.1/admin/includes/languages/english/extra_definitions/mod_list.php
./zc_plugins/ModList/1.4.1/admin/includes/languages/english/mod_list.php
./zc_plugins/ModList/1.4.1/admin/includes/extra_configures/mod_list.php
./zc_plugins/ModList/1.4.1/admin/mod_list.php
./zc_plugins/ModList/1.4.1/manifest.php
./zc_plugins/ModList/1.4.1/Installer/uninstall.sql
./zc_plugins/ModList/1.4.1/Installer/PluginInstaller.php
./zc_plugins/ModList/1.4.1/Installer/install.sql
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h3 id=&#34;things-to-watch-for-in-the-conversion&#34;&gt;Things to watch for in the conversion&lt;/h3&gt;
&lt;h4 id=&#34;scope-of-variables-in-extra_configures-and-extra_datafiles&#34;&gt;Scope of variables in &lt;code&gt;extra_configures&lt;/code&gt; and &lt;code&gt;extra_datafiles&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;In the encapsulated plugin architecture, the files in &lt;code&gt;extra_configures&lt;/code&gt; and &lt;code&gt;extra_datafiles&lt;/code&gt; are run in the context of  the &lt;code&gt;FileSystem&lt;/code&gt; class,
and therefore any variables created will be scoped into that class and not the global scope.&lt;/p&gt;
&lt;p&gt;This means if you have a file that was in &lt;code&gt;admin/includes/extra_configures/my_plugin.php&lt;/code&gt; which created a variable (say, &lt;code&gt;$my_list&lt;/code&gt;), this variable will not be available to the plugin anymore.&lt;/p&gt;
&lt;p&gt;Some options for overcoming this are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Move the logic to a page specific init file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make the variables into defined constants (which by definition have global scope).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;explicit-include-or-require-of-storefront-files&#34;&gt;Explicit &lt;code&gt;include&lt;/code&gt; or &lt;code&gt;require&lt;/code&gt; of storefront files&lt;/h4&gt;
&lt;p&gt;TBD&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Dev: Upgrading Encapsulated Plugins</title>
      <link>https://docs.zen-cart.com/dev/plugins/encapsulated/upgrading/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://docs.zen-cart.com/dev/plugins/encapsulated/upgrading/</guid>
      <description>
        
        
        &lt;p&gt;Once you have created an encapsulated plugin, upgrading it is mostly a matter of creating a new version number under the plugin name, and then making your changes.&lt;/p&gt;
&lt;p&gt;So if the old version was structured like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;zc_plugins/MyPlugin/1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;you can duplicate this to&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;zc_plugins/MyPlugin/1.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and make your changes.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using GitHub for your plugin, then commit the new directory to your repository before making new changes for the new version.&lt;/p&gt;
&lt;p&gt;Once you release, end-users will upload the new version-number directory to their server and run through the upgrade process using Admin &amp;gt; Modules &amp;gt; Plugin Manager.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; An &lt;code&gt;Installer/install.sql&lt;/code&gt; file is ONLY run on NEW installs, not upgrades.
So if your plugin makes any database changes, be sure to update:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Installer/ScriptedInstaller.php&lt;/code&gt; to use &lt;code&gt;executeUpgrade()&lt;/code&gt; to perform any queries (if any) required by the new version. (This is the &lt;strong&gt;only way&lt;/strong&gt; to apply db updates in an upgrade.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Installer/install.sql&lt;/code&gt; (IF used) to include (in addition to any prior queries) any new things added by your upgraded version.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Installer/uninstall.sql&lt;/code&gt; (IF used) to include all (in addition to any prior) removals required to fully remove.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TO BE CLEAR: The &lt;code&gt;ScriptedInstaller.php&lt;/code&gt; (and &lt;code&gt;install.sql&lt;/code&gt; and &lt;code&gt;uninstall.sql&lt;/code&gt; if they exist (they&amp;rsquo;re not required)) MUST be capable of handling BOTH fresh installs AND upgrades across ALL versions that your plugin supports. THERE IS NO &amp;ldquo;INCREMENTAL&amp;rdquo; UPGRADE SUPPORT BASED ON FILENAMES OR VERSION NUMBERS. Any &amp;ldquo;incremental&amp;rdquo; upgrade steps would be coded into your ScriptedInstaller.php script, taking care of doing all requisite dependency checks there.&lt;/p&gt;

      </description>
    </item>
    
  </channel>
</rss>
