0byt3m1n1
Path:
/
data
/
applications
/
aps.bak
/
coppermine
/
1.5.12-0
/
standard
/
htdocs
/
docs
/
es
/
[
Home
]
File: dev_plugins.htm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr"> <head> <title>Plugin Writing - Coppermine Photo Gallery - Documentation & Manual</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="language" content="en" /> <meta name="copyright" content="Coppermine dev team" /> <meta name="description" content="writing plugins for Coppermine" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta name="MSSmartTagsPreventParsing" content="true" /> <meta http-equiv="imagetoolbar" content="no" /> <!-- SVN version info: Coppermine version: 1.5.12 $HeadURL: https://coppermine.svn.sourceforge.net/svnroot/coppermine/trunk/cpg1.5.x/docs/es/dev_plugins.htm $ $Revision: 8154 $ $Date: 2011-01-02 20:44:22 +0100 (So, 02 Jan 2011) $ --> <link rel="stylesheet" type="text/css" href="../style/style.css" media="all" /> <link rel="stylesheet" type="text/css" href="../style/screen.css" media="screen" /> <link rel="stylesheet" type="text/css" href="../style/print.css" media="print" /> <link rel="shortcut icon" href="../favicon.ico" /> <script src="../js/jquery.js" type="text/javascript"></script> <script src="../js/jquery.treeview.js" type="text/javascript"></script> <script src="script.js" type="text/javascript"></script> </head> <body> <h1 id="docheader">Coppermine Photo Gallery v1.5.x: Documentation and Manual</h1> <div id="toc"> <a href="toc.htm">Table of Contents</a> </div> <div id="doc_en_only">No translation available</div> <a name="plugin_writing"></a><h1>Plugin Writing for Coppermine<a href="#plugin_writing" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h1> <a name="plugin_writing"></a><h2>Quick Start Guide<a href="#plugin_writing" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Coppermine comes with a plugin architecture that allows skilled users to come up with plugins that can be installed by the end user with just some clicks in the plugin manager section. Main benefit of plugins is that end users don't have to hack core code files. As a result, plugins don't need to be applied when upgrading between minor versions of coppermine (when replacing all core files due to maintenance releases).</p> <p>Many things that could be done using core hacks can be accomplished using plugins as well. The only disadvantage of plugins is the fact that the plugin author needs to become a bit more familiar with coppermine's plugin API.</p> <p>This short guide is supposed to help possible plugin authors to get familiar with the plugin system. You have to understand though that this section will not teach you how to edit PHP - this would be beyond the scope of this documentation. We asume that you're familar both with HTML as well as PHP to some extent. This section of the docs will definitely <strong>not</strong> teach you how to code in the first place, nor is it a beginner's tutorial for programming. If you have never written one line of PHP code you should get familiar with PHP first and apply some hacks before actually considering to come up with a plugin of your own.</p> <p>Plugins from Coppermine 1.4.x may not work in 1.5. If the plugin uses superglobals like $_POST and $_GET, you need to rewrite those superglobal calls using the new code sanitization in 1.5. See the section "<a href="#plugin_writing_globals">Use of Superglobals</a>". Also, the plugin may include Coppermine files that Coppermine 1.5 now includes for you. You can change "require" to "require_once" or remove the call if Coppermine will always include the file you want. Finally, check the notices under the Debug box to see if any constants you define may already be defined by Coppermine and include checks in the plugin before defining such constants.</p> <a name="plugin_writing_target_audience"></a><h2>Intended Audience<a href="#plugin_writing_target_audience" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Here's a list of who should and who should not (or doesn't need to) read this documentation. The categories overlap in many places, so make sure to read the entire list. Find yourself in the list and then decide whether you should read on.</p> <div id="ulgreen" class="cpg_message_success"> <a name="plugin_writing_target_audience_yes"></a><h4>People who <em>should</em> read this documentation:<a href="#plugin_writing_target_audience_yes" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> <ul type="square"> <li>Anyone who wants to write plugins to customize Coppermine</li> <li>Current Coppermine coders who want to convert their hacks & mods to plugins</li> <li>Anyone who wants to add in features or modify a current plugin</li> <li>Coders who want to start customizing Coppermine but do not know where to start</li> </ul> </div> <div id="ulred" class="cpg_message_validation"> <a name="plugin_writing_target_audience_no"></a><h4>People who do <em>not</em> need to read this documentation:<a href="#plugin_writing_target_audience_no" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> <ul> <li>Anyone learning Coppermine for the first time - the <a href="index.htm">main manual</a> is all you need at first</li> <li>Anyone who wants to download & use plugins - you can use many plugins without knowing what they do internally</li> </ul> </div> <p>People interested in using plugins but who do not need to modify them or write their own should read the main documentation instead - <a href="plugins.htm">the plugins section</a> describes everything you need to know.</p> <a name="plugin_writing_why_write"></a><h2>Why write plugins?<a href="#plugin_writing_why_write" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>The biggest advantage of a plugin over a mod is the fact that plugins will remain when updating Coppermine, while mods (<abbr title="also known as">aka</abbr> "modifications" or "hacks") need to be re-applied after updating.</p> <p>It's pretty easy to come up with a plugin of your own. This page and it's sub-pages is meant to explain how to come up with your first home-made plugin.</p> <a name="plugin_writing_preparation"></a><h2>Preparations<a href="#plugin_writing_preparation" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Before starting to hack away, you should make some preparations and maybe sketch the layout of your plugin.</p> <ul> <li> <a name="plugin_writing_preparation_name"></a><h3>Choose a name<a href="#plugin_writing_preparation_name" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Your plugin needs a meaningfull, simple name. Make sure that a plugin doesn't already exist with the same name you've chosen. Then create a sub-folder within the plugin folder and name it as you see fit. Make sure to use web-safe names (only alphanumerals, all lower-case, no special chars except underscore.<br /> For clarification: there can be only alphanumerals in a plugin's folder name. There mustn't be any dots or other special chars in it. The only exception is the underscore (_) <div class="cpg_example"><tt class="code">your_coppermine_folder/plugins/coffee_maker/</tt></div> Coming up with a folder name sounds easy, and you may be tempted to just use the name <tt class="code">my_plugin</tt> or <tt class="code">foobar</tt> to be able to start coding right away. However, you have to keep in mind that while you progress writing your plugin, the folder name will appear hard-coded into your plugin (possibly many times), so it will be hard to change it later. That's why it's advisable to come up with a good folder name in the first place: it should be descriptive, consist of two or three words and mean something initially. A folder named "<tt class="code">coppermine_candy</tt>" wouldn't mean much - the word "coppermine" would make no point, as the plugin already resides within coppermine, and the word "candy" would no describe what your plugin does. Better, self-explanatory names for plugins would be "rename_users", "thumbnail_dropshadow" or "backup_files". If someone else already has created a plugin that will do something similar to your plugin, make sure to use a name that differs from the other plugin. The second part of your plugin's name could be your nickname or real name as well - something like "slideshow_nick" as a plugin short name would be OK. It's not a bright idea to try to "cheat" by naming your plugin "aaaaaaa" in an attempt to make it stand out in the plugin list (the plugin list is sorted alphabetically) - the staff on coppermine-gallery.net will rename such plugins. Also please don't use abbreviations that don't mean anything - names like "dffds" for "damn fast flash-driven slideshow" are not easy to memorize - instead you should use something like "slideshow_flash"; if a user looks at the list of plugins on his gallery using his FTP application (during upload), it should be obious what plugin each sub-folder corresponds to. <br /> For details on a good name for your folder, please read up the sections "<a href="#plugin_writing_naming_conventions">Naming conventions</a>" and "<a href="dev_plugin_api.htm#plugin_api_">Distributing Your Plugin</a>" as well.</li> <li> <a name="plugin_writing_preparation_translation"></a><h3>Consider translations<a href="#plugin_writing_preparation_translation" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Coppermine is an international project, with users from all over the world. If you should decide to contribute your custom plugin later, it would be a good idea to design it properly in the first place: keep all strings that could need translation in a separate include file and only hard-code the corresponding vars into your code. </li> <li> <a name="plugin_writing_preparation_config"></a><h3>Consider a config screen<a href="#plugin_writing_preparation_config" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> If your plugin is only going to add one single feature to coppermine without anything to configure, then there's no need to provide a separate config screen for your plugin. However, if your plugin has options the end user could configure, it's a good idea to come up with a config screen for your plugin. </li> <li> <a name="plugin_writing_preparation_db"></a><h3>Database changes<a href="#plugin_writing_preparation_db" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> If your plugin needs to write to the database or even changes the structure of tables, it's almost mandatory to come up with a routine to write the needed database changes during install of the plugin. It's a good idea as well to come up with a method to undo the database changes if the user should later decide to disable/uninstall your plugin. If this is the case, you should preferably come up with a database setup screen as well (see "<a href="#plugin_writing_database">Database access</a>"). </li> <li> <a name="plugin_writing_preparation_support"></a><h3>Support issues<a href="#plugin_writing_preparation_support" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> For every non-trivial plugin that gets published on the coppermine home page, there will be an announcement thread on the board. It's a good idea to provide the URL of the announcement thread together with your plugin, preferably even a clickable link. </li> <li> <a name="plugin_writing_preparation_versions"></a><h3>Plugin versions<a href="#plugin_writing_preparation_versions" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Although you may not plan to develop your plugin even further, others may do so. Therefore, it's a good idea to provide a version number with your plugin. </li> </ul> <a name="plugin_writing_core_files"></a><h2>Core files<a href="#plugin_writing_core_files" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Every plugin contains at least two mandatory files: codebase.php and configuration.php:</p> <ul> <li><a name="plugin_writing_core_files_codebase"></a><h3>codebase.php<a href="#plugin_writing_core_files_codebase" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> In this file, the various actions that a plugin can execute are being defined. Think of it as the plugin's core file, where the core logic of the plugin resides in. </li> <li><a name="plugin_writing_core_files_configuration"></a><h3>configuration.php<a href="#plugin_writing_core_files_configuration" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> When the plugin manager is run, it scans through all sub-folders of the plugins folder and looks for a file named <tt class="code">configuration.php</tt>. If such a file exists, the information provided within this file will be displayed as a record in the list of not-installed or installed plugins.<br /> <br /> You can use these vars inside configuration.php: <ul> <li><a name="plugin_writing_core_files_configuration_name"></a><h4>$name<a href="#plugin_writing_core_files_configuration_name" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> The full name of your plugin (not only the web-safe folder name chosen initially, but a name that indicates what the plugin does).<br /> <div class="cpg_code code"><strong>$name</strong> = 'Coffee Maker';</div> </li> <li><a name="plugin_writing_core_files_configuration_description"></a><h4>$description<a href="#plugin_writing_core_files_configuration_description" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> A short description that explains what your plugin actually does.<br /> <div class="cpg_code code"><strong>$description</strong> = 'Turns your Coppermine gallery into a coffee machine.';</div> </li> <li><a name="plugin_writing_core_files_configuration_author"></a><h4>$author<a href="#plugin_writing_core_files_configuration_author" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> Obviously, this is the place for your credits. You can use your real name or a nickname (or even both). You can even slightly promote your site by adding a link to it within the content of this variable.<br /> <div class="cpg_code code"><strong>$author</strong> = 'John Smith (aka "<a href="http://yoursite.tld/" rel="external" class="external">NeoIsDead</a>").';</div> </li> <li><a name="plugin_writing_core_files_configuration_version"></a><h4>$version<a href="#plugin_writing_core_files_configuration_version" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> The version of your plugin - usually starting with 1.0 (although you're welcome to come up with any other numbering scheme as long as the difference between versions will be obvious). A lot of coders try to indicate the stage their code is in using the first digit of the version number. That's why many start modestly counting from zero, with the zero versions indicating alpha or beta stage. While the coppermine dev team welcomes this for entire applications we don't consider this usefull for a plugin, which is not an application of it's own, but just "lives" within the application as an add-on. That's why the Coppermine dev team recommends starting to count from one for the first digit and zero for the second digit. Using a third digit is inappropriate for nearly all plugins.<br /> <div class="cpg_code code"><strong>$version</strong> = '1.0';</div> </li> <li><a name="plugin_writing_core_files_configuration_plugin_cpg_version"></a><h4>$plugin_cpg_version<a href="#plugin_writing_core_files_configuration_plugin_cpg_version" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> Specify the minimum coppermine version number that your plugin will work with. It is advisable to only specify the major version (i.e. <tt class="code">'1.5'</tt>) if you're not using a plugin hook that has been added to the core at a later stage.<br /> If you already know that limit, you can speficy a maximum version as well (although that's an optional feature). <div class="cpg_code code"><strong>$plugin_cpg_version</strong> = array('min' => '1.5');</div> The minimum version number you specify will be compared against the constant <tt class="code">COPPERMINE_VERSION</tt> on the <a href="plugins.htm#plugin_manager_install">plugin manager</a> page for the plugins that can be installed. </li> <li><a name="plugin_writing_core_files_configuration_extra_info"></a><h4>$extra_info<a href="#plugin_writing_core_files_configuration_extra_info" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> Is displayed with the title of a plugin that is <strong>not</strong> installed and can be used to present extra information. Use it for example to present an additional link to the plugin documentation if your plugin needs detailed explanation. When using larger pieces of HTML, it's recommended to use the heredoc-syntax to define the variable to make the code better readable.<br /> <div class="cpg_code code"><strong>$extra_info</strong> = <<<EOT<br /> <table border="0" cellspacing="0" cellpadding="0"><br /> <tr><br /> <td class="admin_menu"><br /> <a href="http://yoursite.tld/coffee_maker/docs/" title="Plugin Documentation" rel="external" class="external">Documentation</a><br /> </td><br /> </tr><br /> </table><br /> EOT;</div> </li> <li><a name="plugin_writing_core_files_configuration_install_info"></a><h4>$install_info<a href="#plugin_writing_core_files_configuration_install_info" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h4> Is displayed with the title of a plugin that <strong>is</strong> installed and can be used to present extra information. When using larger pieces of HTML, it's recommended to use the heredoc-syntax to define the variable to make the code better readable.<br /> <div class="cpg_code code"><strong>$install_info</strong> = <<<EOT<br /> <div class="admin_menu_wrapper"><br /> <div class="admin_menu admin_float"><br /> <a href="index.php?file=coffee_maker/admin&action=config" title="Configuration">Plugin configuration</a><br /> </div><br /> <div class="admin_menu admin_float"><br /> <a href="http://coppermine-gallery.net/forum/index.php?foo=bar" title="Plugin Support">Support thread</a><br /> </div><br /> <div style="clear:left;"></div><br /> </div><br /> EOT;</div> </li> </ul> </li> <li><a name="plugin_writing_core_files_readme"></a><h3>readme.txt<a href="#plugin_writing_core_files_readme" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> It's a good idea (not mandatory though) to provide a plain-text file within your plugin's folder as well (readme.txt or similar) that contains copyright and support information and basic instructions what your plugin does and how the end user can install it.<br /> It's not a bad idea to include a changelog and license information in that readme file.</li> </ul> <a name="plugin_writing_naming_conventions"></a><h2>Naming conventions<a href="#plugin_writing_naming_conventions" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Even if you plan to write a plugin just for your purposes you should pay attention to the naming conventions for plugins to make sure that your plugin will not stop working as expected at a later stage (e.g. after an update).</p> <p>The naming conventions exist for two purposes: they enable Coppermine's developers to come with restrictive rules for Coppermine's core code to prevent hacking. Unsanitized user input can have a huge impact in hacking scenarios, that's why there are rules for plugins as well. Additionally, naming conventions are supposed to make maintenance and support easier, and finally, end users will find their way around easier as well.</p> <ul> <li> <a name="plugin_writing_naming_conventions_folders"></a><h3>Folders<a href="#plugin_writing_naming_conventions_folders" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Use web-safe names: <ul> <li>only alphanumerals</li> <li>all lower-case</li> <li>no special chars except underscore (_)</li> </ul> <div class="cpg_example"><tt class="code">your_coppermine_folder/plugins/coffee_maker/</tt></div> </li> <li> <a name="plugin_writing_naming_conventions_files"></a><h3>Files<a href="#plugin_writing_naming_conventions_files" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Use web-safe names: <ul> <li>only alphanumerals</li> <li>all lower-case</li> <li>no special chars except underscore (_) and only one dot (.) to separate the actual file name from the extension</li> </ul> <div class="cpg_example"><tt class="code">your_coppermine_folder/plugins/coffee_maker/my_file.php</tt></div> </li> <li> <a name="plugin_writing_naming_conventions_archives"></a><h3>Archives<a href="#plugin_writing_naming_conventions_archives" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> You only need to worry about naming conventions for archives if you plan to release your plugin for the public. The zip-archives for plugin releases follow a naming convention - it's advisable to adopt to that convention to prevent confusion for end-users. <ul> <li>only alphanumerals</li> <li>all lower-case</li> <li>no special chars except underscore (_), hyphen (-) and dot (.)</li> <li>All archives start with the official abbreviation "<tt class="code">cpg</tt>" to indicate that the archive is meant to be used with coppermine or is related to coppermine</li> <li>The major version an archive is meant to be used with comes right after that - the minor version being replaced with an <tt class="code">x</tt>. Possible values for plugins can currently be <tt class="code">1.4.x</tt> and <tt class="code">1.5.x</tt>. The Coppermine version is being followed by an underscore</li> <li>The word "plugin" to indicate that the archive contains a plugin (opposed to a theme or similar), followed by an underscore</li> <li>The name of the actual plugin, preferably using the same name that has been used as folder name. The plugin name should usually consist of at least two words. Unlike the <a href="#plugin_writing_naming_conventions_folders">naming convention for folders</a>, the words in the archive name are being separated with hyphens (-) to make them distinguishable from the underscore that separates the components of the file name. In above example, where the folder name <tt class="code">coffee_maker</tt> was used, the corresponding part of the archive file name would be <tt class="code">coffee-maker</tt>.<br /> To separate the actual plugin name component in the file name from the rest, another underscore should be used</li> <li>All plugins have versions. Even if you don't plan to create more versions after having released your initial plugin, others may want to do so. That's why you should always populate the version number inside <tt class="code">configuration.php</tt>. The same version should show through in the archive file name, with the letter "<tt class="code">v</tt>" prepended to indicate the word "version". Major and minor version numbers should be separated with dots. Coppermine itself currently features three digits for the version number. We advise plugin authors to use a two-digits version numbering scheme, where the first digit indicates the major version and the second digit indicates the minor version change (usually a maintenance release). <br />This two-digit version numbering scheme for plugins is not written in stone - plugin authors can use a three-digit notation as well if they desire.<br /> The Coppermine dev team suggests starting the numbering at version 1.0</li> <li>The extension <tt class="code">zip</tt> can of course not be edited. We strongly suggest only to use zip and not some other archive format like <tt class="code">rar</tt> or <tt class="code">7z</tt> even if those other formats may have advantages. The archive-type <tt class="code">zip</tt> is most commonly used; everybody should have a tool to extract zip files.</li> </ul> <div class="cpg_example"> <strong>Example</strong>:<br /> <tt class="code">cpg1.5.x_plugin_coffee-maker_v1.0.zip</tt> </div> </li> <li> <a name="plugin_writing_naming_conventions_coding"></a><h3>Coding<a href="#plugin_writing_naming_conventions_coding" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> <p>There are naming conventions as well as far as the stuff within your files is concerned: you should take a look at the <a href="dev_coding.htm#dev_coding_naming_conventions">coding guidelines</a> for Coppermine as well to get an idea how to name your functions, variables and constants.</p> </li> </ul> <a name="plugin_writing_globals"></a><h2>Use of Superglobals<a href="#plugin_writing_globals" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> If you are going to use superglobals in your plugin, you will have to take notice of the Coppermine <a href="dev_superglobals.htm">code sanitization</a>.<br> You will also have to include the following line to make sure you can use these superglobals: <div class="quote"> $superCage = Inspekt::makeSuperCage(); </div><br /> Double check this if you're getting a 500 error. <a name="plugin_writing_database"></a><h2>Database access<a href="#plugin_writing_database" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> A plugin can access the database in the same manner that core code is accessing the database. However, there are some things to keep in mind for plugin authors: <a name="plugin_writing_database_direct_queries"></a><h3>Direct queries<a href="#plugin_writing_database_direct_queries" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Don't use the native PHP commands (like <a href="http://www.php.net/manual/en/function.mysql-query.php" rel="external" class="phpnet">mysql_query</a>) to perform queries against the coppermine database tables. Instead, use the function <tt class="code">cpg_db_query</tt> built into coppermine. You don't need to explicitely open the connection - it is already established for you when using the plugin API. <div class="cpg_example"> <table border="0" cellspacing="0" cellpadding="0" width="100%" class="maintable"> <tr> <td class="tableb">Bad example</td> <td class="tableb cpg_message_validation code">$result = mysql_query("SELECT * WHERE 1=1");</td> </tr> <tr> <td class="tableb tableb_alternate">Good example</td> <td class="tableb cpg_message_success code">$result = cpg_db_query("SELECT * WHERE 1=1");</td> </tr> </table> </div> <a name="plugin_writing_database_tables_access"></a><h3>Accessing database tables<a href="#plugin_writing_database_tables_access" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> Don't hard-code table names into your custom queries, as your queries are bound to break if users have chosen another table prefix than the default one.<br /> Instead, coppermine defines a variable <tt class="code">$CONFIG['TABLE_PREFIX']</tt> that contains the table prefix that you can (and should) use if you need to access a table within coppermine's database and using the prefix: use the prefix for custom tables for your plugin. <div class="cpg_example"> <table border="0" cellspacing="0" cellpadding="0" width="100%" class="maintable"> <tr> <td class="tableb">Bad example</td> <td class="tableb cpg_message_validation code">$result = cpg_db_query("SELECT * FROM cpg15x_plugin_example WHERE 1=1");</td> </tr> <tr> <td class="tableb tableb_alternate">Good example</td> <td class="tableb cpg_message_success code">$result = cpg_db_query("SELECT * FROM {$CONFIG['TABLE_PREFIX']}plugin_example WHERE 1=1");</td> </tr> </table> </div> If you want to access an existing table (like the coppermine table that contains all categories), use the variables outlined in <a href="dev_database.htm#db_reference within_code">Database reference within coppermine code</a>. <div class="cpg_example"> <table border="0" cellspacing="0" cellpadding="0" width="100%" class="maintable"> <tr> <td class="tableb">Bad example</td> <td class="tableb cpg_message_validation code">$result = cpg_db_query("SELECT * FROM {$CONFIG['TABLE_PREFIX']}categories WHERE 1=1");</td> </tr> <tr> <td class="tableb tableb_alternate">Good example</td> <td class="tableb cpg_message_success code">$result = cpg_db_query("SELECT * FROM $CONFIG['TABLE_CATEGORIES'] WHERE 1=1");</td> </tr> </table> </div> <a name="plugin_writing_database_tables_create"></a><h3>Creating database tables<a href="#plugin_writing_database_tables_create" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> If you need to expand the database schema of coppermine to add a table for your plugin, you should follow the following rules: <ul> <li>Create your table within the same database that coppermine resides in</li> <li>Respect the naming scheme by prefixing your table name with the table prefix that the user has chosen during install (stored in <tt class="code">$CONFIG['TABLE_PREFIX']</tt>), followed by the word "plugin" with an underscore, followed by the short name of your plugin (the "<a href="#plugin_writing_naming_conventions_folders">folder name of your plugin</a>") <div class="cpg_example">If your plugin folder name was "coffee_maker", your plugin's table name would be <tt class="code">$CONFIG['TABLE_PREFIX']</tt> . '_plugin_coffee_maker' </div> </li> <li>During your plugin's install function, make sure that your table creation progress doesn't break if a user hasn't removed your plugin previously - it's recommended to use <tt class="code">CREATE TABLE IF NOT EXISTS</tt> instead of just using <tt class="code">CREATE TABLE</tt></li> <li>Don't consume more resources than you need - define the types and dimensions of your plugin fields wisely</li> </ul> This could be an example for a database table creation query inside your plugin's install function: <pre class="cpg_code code">$query = <<< EOT CREATE TABLE IF NOT EXISTS `{$CONFIG['TABLE_PREFIX']}plugin_coffee_maker` ( `cid` mediumint(10) NOT NULL default '0', `some_field` smallint(6) NOT NULL default '0' ) COMMENT='Your clever description of the table here'; EOT; $result = cpg_db_query($query); </pre> <a name="plugin_writing_database_tables_delete"></a><h3>Deleting database tables<a href="#plugin_writing_database_tables_delete" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> It's important that your plugin removes all tables it created during install when the end user uninstalls it. In some rare cases it might make sense to keep the database tables if the user decides to install it later again (if the re-population of the database table records would be time-consuming or complicated). If that's the case for your plugin, you should add a form to the uninstall process of your plugin that asks the end user if the database table should be kept or not. Out of the box, the database tables that were created during install need to be deleted when the plugin is uninstalled.<br /> It's safer to use <tt class="code">DROP TABLE IF EXISTS</tt> instead of just using <tt class="code">DROP TABLE</tt>. To get rid of the table created in the example above, run a query like <pre class="cpg_code code">cpg_db_query("DROP TABLE IF EXISTS {$CONFIG['TABLE_PREFIX']}plugin_coffee_maker");</pre>in the uninstall function of your plugin. <a name="plugin_writing_database_config"></a><h3>Storing your plugin's config values<a href="#plugin_writing_database_config" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h3> If you need just a few database records to store your plugin's config settings, you don't have to create a separate table just for those few plugin config records - instead, you're encouraged to use the existing config table where coppermine stores it's core settings in as well. There are some great benefits in using the existing config table: the main benefit is that you don't have to run a query to get your setting's values - coppermine's core code will populate the <tt class="code">$CONFIG</tt>-array insteadd accordingly.<br /> It's important though that it get's obvious what your config records are being used for and from which plugin they come from. That's why there is a strict naming schema for new records in coppermine's config that a plugin should adhere to: prefix the record with the word "plugin" followed by an underscore followed by your plugin's short name followed by an underscore followed by the actual config setting name.<br /> To make sure that your script doesn't break if such a setting already exists (e.g. if the user re-installs your plugin that hasn't been uninstalled properly before) it's advisable to use <tt class="code">INSERT IGNORE</tt> instead of using an ordinary <tt class="code">INSERT</tt>. <div class="cpg_example"> If your plugin's short name is "coffee_maker" and you need to store a setting for the height of the coffee mug with the default value of 20, the corresponding setting record could be named <tt class="code">plugin_coffee_maker_mug_height</tt><br /> The query in the install section of your plugin could be something like <pre clas="cpg_code">cpg_db_query("INSERT IGNORE INTO {$CONFIG['TABLE_CONFIG']} ( `name` , `value` ) VALUES ('plugin_coffee_maker_mug_height', '20')");</pre>and the corresponding line inside the uninstall section would be<pre clas="cpg_code">cpg_db_query("DELETE FROM {$CONFIG['TABLE_CONFIG']} WHERE name = 'plugin_coffee_maker_mug_height'");</pre> The resulting element inside the <tt class="code">$CONFIG</tt> array would be <tt class="code">$CONFIG['plugin_coffee_maker_mug_height']</tt> </div> <a name="plugin_writing_types"></a><h2>Plugin Types<a href="#plugin_writing_types" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> Plugins (or rather individual pages of a plugin) can roughly fall into two categories: they can reside on a page of their own (a good example would be the plugin config screen some plugins come with or a plugin that adds a contact form) or they can reside within each or some coppermine-driven pages, modifying the output or functionality of the pages they reside on (a good example would be plugins that add menu items).<br /> It is comparatively easy to come up with plugins that fall into the first category (creating additional pages). The second option is the more advanced and powerfull option that plugins authors can use. For this purpose, there are "anchors" all over coppermine's core code that allow plugin interaction with the code, the so-called "<a href="dev_plugin_hooks.htm">plugin hooks</a>". <a name="plugin_writing_includes"></a><h2>Using includes<a href="#plugin_writing_includes" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Files the plugin is meant to include on the index page of the gallery can only contain one single dot that separates the actual filename from the php-extension, as suggested in "<a href="dev_plugin_api.htm#plugin_api_tutorial_linking">Linking to Custom Plugin Scripts</a>"</p> <a name="plugin_writing_sub_sections"></a><h2>Sub-sections<a href="#plugin_writing_sub_sections" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>These plugin documents are a work-in-progress, and a to-do list. The following sub-sections exist so far that are recommended to read:</p> <ul> <li><a href="dev_plugin_api.htm">Tutorial, Plugin API</a><br />The tutorial is the next logical step to follow after having read the quick start guide</li> <li><a href="dev_plugin_hooks.htm">Reference List of Plugin Hooks</a><br /> The reference list is meant as a source for experienced plugin writer who need to look up the names of hooks.</li> <li>Global <a href="dev_vars.htm">Variables & Constants</a> in Coppermine</li> </ul> <a name="plugin_writing_recommended"></a><h2>Recommended reading<a href="#plugin_writing_recommended" title="Link to this section"><img src="images/anchor.gif" width="15" height="9" border="0" alt="" /></a></h2> <p>Although primarily written for dev team members it's recommended for plugin authors to review the <a href="dev_coding.htm#dev_coding">coding guidelines</a> for coppermine.</p> <br clear="all" /> <div id="doc_footer"> <div class="doc_info_wrapper"> <span id="doc_last_changed">$LastChangedDate: 2011-01-02 20:44:22 +0100 (So, 02 Jan 2011) $</span> <span id="doc_revision">$Revision: 8154 $</span> </div> </div> </body> </html>