(Created page with '__TOC__{{CKFinder 2.x Writing Plugins Introduction}} == Creating a plugin == ==== Step1: Create plugin folder ==== Create a directory for your plugin inside of the "plugins" di…') |
|||
Line 8: | Line 8: | ||
==== Step2: Create plugin file ==== | ==== Step2: Create plugin file ==== | ||
− | Inside of your plugin's folder ("myplugin") create an empty file named '''plugin. | + | Inside of your plugin's folder ("myplugin") create an empty file named '''plugin.asp'''. |
==== Step3: Add plugin definition ==== | ==== Step3: Add plugin definition ==== | ||
− | // Let's create an empty | + | // Let's create an empty ASP file for now |
==== Step4: Enable plugin ==== | ==== Step4: Enable plugin ==== | ||
− | Add an | + | Add an INCLUDE statement in the ASP configuration file (config.asp): |
− | <source lang=" | + | <source lang="asp"> |
− | + | <!-- #INCLUDE file="plugins/myplugin/plugin.asp" --> | |
</source> | </source> | ||
− | == | + | == ASP plugin system == |
=== Hooks === | === Hooks === | ||
Line 28: | Line 28: | ||
CKFinder provides several hooks that can be used to extend the functionality of the CKFinder application. Assigning a function (also known as an event handler) to a hook will cause that function to be called at the appropriate point in the main CKFinder code, to perform whatever additional task(s) the developer thinks would be useful at that point. Each hook can have multiple handlers assigned to it, in which case it will call the functions in the order that they are assigned. | CKFinder provides several hooks that can be used to extend the functionality of the CKFinder application. Assigning a function (also known as an event handler) to a hook will cause that function to be called at the appropriate point in the main CKFinder code, to perform whatever additional task(s) the developer thinks would be useful at that point. Each hook can have multiple handlers assigned to it, in which case it will call the functions in the order that they are assigned. | ||
− | Hooks should be assigned in a plugin file. | + | Hooks should be assigned in a plugin file. To assign a event listener to a hook call: |
− | <source lang=" | + | <source lang="asp"> |
− | + | CKFinder_AddHook "EventName", CommandHandler | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source> | </source> | ||
+ | where EventName is the name of a hook and CommandHandler is an object that contains a method named '''On'''EventName. | ||
==== Available hooks ==== | ==== Available hooks ==== | ||
Line 59: | Line 53: | ||
but the advantage of defining it in plugin.php is that it will be enabled only when the server side plugin is also enabled. | but the advantage of defining it in plugin.php is that it will be enabled only when the server side plugin is also enabled. | ||
− | {{CKFinder_2.x Sample Plugin Introduction|ext= | + | {{CKFinder_2.x Sample Plugin Introduction|ext=asp}} |
+ | |||
+ | For the sake of simplicity, we'll first create a simple '''plugin.asp''' that just does exactly what we need: | ||
+ | <source lang="asp"> | ||
+ | <script runat="server" language="VBScript"> | ||
+ | |||
+ | class CKFinder_Connector_CommandHandler_FileSize | ||
+ | 'pseudo inheritance | ||
+ | private base | ||
+ | |||
+ | ' Since we want to send a XML response, we'll extend the XmlCommandHandlerBase class | ||
+ | Private Sub Class_Initialize() | ||
+ | Set base = new CKFinder_Connector_CommandHandler_XmlCommandHandlerBase | ||
+ | Set base.child = me | ||
+ | End Sub | ||
+ | |||
+ | ' Pseudo inheritance | ||
+ | Public Property Get currentFolder() | ||
+ | Set currentFolder = base.currentFolder | ||
+ | End Property | ||
− | + | Public Sub sendResponse(response) | |
− | + | base.sendResponse(response) | |
− | + | End sub | |
+ | |||
+ | Public Property Get ErrorHandler() | ||
+ | Set ErrorHandler = base.ErrorHandler | ||
+ | End Property | ||
+ | |||
+ | ' (5) The buildXml method is used to construct an XML response | ||
+ | function buildXml( oXML ) | ||
+ | Dim fileName | ||
+ | fileName = request("fileName") | ||
+ | |||
+ | Dim oUFS | ||
+ | Set oUFS = oCKFinder_Factory.UtilsFileSystem | ||
+ | |||
+ | Dim filePath | ||
+ | filePath = oUFS.combinePaths(currentFolder.getServerPath(), fileName) | ||
+ | |||
+ | ' (6) Adding a <FileSize> element to the XML response. | ||
+ | Dim size, oNode | ||
+ | size = oUFS.GetFileSize(filePath) | ||
+ | Set oNode = oXML.connectorNode.addChild("FileSize") | ||
+ | oNode.addAttribute "size", size | ||
+ | |||
+ | End function | ||
− | + | ' Our event listener: | |
− | + | ' (3) Register the "FileSize" command | |
+ | public function onBeforeExecuteCommand( command ) | ||
+ | if ( command = "FileSize" ) then | ||
+ | ' The sendResponse method is defined in XmlCommandHandlerBase, it creates | ||
+ | ' a basic XML response and calls the buildXml()method | ||
+ | sendResponse( response ) | ||
+ | ' false = stop further execution. | ||
+ | onBeforeExecuteCommand = False | ||
+ | Exit function | ||
+ | End if | ||
− | + | onBeforeExecuteCommand = True | |
− | + | End Function | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | End Class | |
− | |||
− | |||
− | |||
− | |||
− | + | Dim CommandHandler_FileSize | |
− | + | Set CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ' Object assigned to a hook must contain event listener named "onEventName" | |
− | + | ' (the event name is BeforeExecuteCommand, so we must define an onBeforeExecuteCommand method). | |
− | + | CKFinder_AddHook "BeforeExecuteCommand", CommandHandler_FileSize | |
+ | CKFinder_AddPlugin "myplugin" | ||
− | + | </script> | |
− | / | ||
− | |||
</source> | </source> | ||
Line 142: | Line 167: | ||
==== Full source code ==== | ==== Full source code ==== | ||
− | ===== plugin. | + | ===== plugin.asp ===== |
The full source code of a plugin with all necessary security checks: (save the code as '''plugin.php''' in "plugins/myplugin" folder) | The full source code of a plugin with all necessary security checks: (save the code as '''plugin.php''' in "plugins/myplugin" folder) | ||
− | <source lang=" | + | <source lang="asp"> |
− | < | + | <script runat="server" language="VBScript"> |
+ | |||
+ | class CKFinder_Connector_CommandHandler_FileSize | ||
+ | 'pseudo inheritance | ||
+ | private base | ||
+ | |||
+ | ' Since we want to send a XML response, we'll extend the XmlCommandHandlerBase class | ||
+ | Private Sub Class_Initialize() | ||
+ | Set base = new CKFinder_Connector_CommandHandler_XmlCommandHandlerBase | ||
+ | Set base.child = me | ||
+ | End Sub | ||
+ | |||
+ | Private Sub Class_Terminate() | ||
+ | Set base.child = Nothing | ||
+ | Set base = Nothing | ||
+ | End Sub | ||
+ | |||
+ | ' Pseudo inheritance | ||
+ | Public Property Get currentFolder() | ||
+ | Set currentFolder = base.currentFolder | ||
+ | End Property | ||
+ | |||
+ | Public Sub sendResponse(response) | ||
+ | base.sendResponse(response) | ||
+ | End sub | ||
+ | |||
+ | Public Property Get ErrorHandler() | ||
+ | Set ErrorHandler = base.ErrorHandler | ||
+ | End Property | ||
+ | |||
+ | ' (5) The buildXml method is used to construct an XML response | ||
+ | function buildXml( oXML ) | ||
+ | |||
+ | if not(currentFolder.checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) then | ||
+ | errorHandler.throwError CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED, "", "ACL check failed" | ||
+ | End if | ||
− | + | Dim resourceTypeInfo | |
− | + | Set resourceTypeInfo = currentFolder.getResourceTypeConfig() | |
− | + | Dim fileName | |
− | + | fileName = request("fileName") | |
+ | If (fileName="") then | ||
+ | errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_NAME, "", "Missing filename" | ||
+ | End if | ||
− | + | Dim oUFS | |
− | + | Set oUFS = oCKFinder_Factory.UtilsFileSystem | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | if (Not oUFS.checkFileName(fileName) or resourceTypeInfo.checkIsHiddenFile(fileName)) then | |
− | + | errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST, "", "Invalid filename" | |
− | + | End if | |
− | |||
− | + | if (Not resourceTypeInfo.checkExtension(fileName)) then | |
− | if ( | + | errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST, "", "Invalid extension" |
− | + | End if | |
− | |||
− | + | Dim filePath | |
− | + | filePath = oUFS.combinePaths(currentFolder.getServerPath(), fileName) | |
− | + | If Not(oUFS.fileExists(filePath)) then | |
− | + | errorHandler.throwError CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND, "", "File doesn't exists: " & filePath | |
− | + | End if | |
− | |||
− | + | ' (6) Adding a <FileSize> element to the XML response. | |
− | + | Dim size, oNode | |
− | + | size = oUFS.GetFileSize(filePath) | |
− | + | Set oNode = oXML.connectorNode.addChild("FileSize") | |
+ | oNode.addAttribute "size", size | ||
− | + | End function | |
− | if ( | + | ' Our event listener: |
− | + | ' (3) Register the "FileSize" command | |
− | + | public function onBeforeExecuteCommand( command ) | |
+ | if ( command = "FileSize" ) then | ||
+ | ' The sendResponse method is defined in XmlCommandHandlerBase, it creates | ||
+ | ' a basic XML response and calls the buildXml()method | ||
+ | sendResponse( response ) | ||
+ | ' false = stop further execution. | ||
+ | onBeforeExecuteCommand = False | ||
+ | Exit function | ||
+ | End if | ||
− | + | onBeforeExecuteCommand = True | |
+ | End Function | ||
− | + | End Class | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Dim CommandHandler_FileSize | |
− | + | If (TypeName(oCKFinder_Factory) <> "Empty") then | |
− | + | Set CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ' Object assigned to a hook must contain event listener named "onEventName" | |
− | + | ' (the event name is BeforeExecuteCommand, so we must define an onBeforeExecuteCommand method). | |
− | + | CKFinder_AddHook "BeforeExecuteCommand", CommandHandler_FileSize | |
+ | CKFinder_AddPlugin "myplugin" | ||
+ | End if | ||
− | + | </script> | |
− | / | ||
− | |||
− | |||
− | |||
</source> | </source> | ||
{{CKFinder_2.x myplugin code}} | {{CKFinder_2.x myplugin code}} | ||
{{#CUSTOMTITLE:Writing ASP Plugins}} | {{#CUSTOMTITLE:Writing ASP Plugins}} |
Revision as of 09:25, 26 May 2010
Contents
[hide]The main advantages of plugins are:
- Upgrades are much easier.
- The plugin code is stored in a single place.
- Plugins can be easily disabled when they are not needed anymore.
Common use cases:
- Adding a new server-side command (i.e.
fileditor
andimageresize
plugin). - Working with uploaded files (i.e.
watermark
plugin). - Extending information returned by the
Init
command (i.e.imageresize
plugin).
Creating a plugin
Step1: Create plugin folder
Create a directory for your plugin inside of the "plugins" directory (by default CKFinder comes with three plugins: dummy, fileeditor, imagreresize). Let's use "myplugin" as the plugin name and use the same name for our new folder.
Step2: Create plugin file
Inside of your plugin's folder ("myplugin") create an empty file named plugin.asp.
Step3: Add plugin definition
// Let's create an empty ASP file for now
Step4: Enable plugin
Add an INCLUDE statement in the ASP configuration file (config.asp):
<!-- #INCLUDE file="plugins/myplugin/plugin.asp" -->
ASP plugin system
Hooks
CKFinder provides several hooks that can be used to extend the functionality of the CKFinder application. Assigning a function (also known as an event handler) to a hook will cause that function to be called at the appropriate point in the main CKFinder code, to perform whatever additional task(s) the developer thinks would be useful at that point. Each hook can have multiple handlers assigned to it, in which case it will call the functions in the order that they are assigned.
Hooks should be assigned in a plugin file. To assign a event listener to a hook call:
CKFinder_AddHook "EventName", CommandHandler
where EventName is the name of a hook and CommandHandler is an object that contains a method named OnEventName.
Available hooks
Hook | Since | Description |
---|---|---|
AfterFileUpload | 2.0 | Executed after successful file upload. |
BeforeExecuteCommand | 2.0 | Executed before a server side command is executed. |
InitCommand | 2.0 | Executed straight before sending the result of the Init command. |
Enabling JavaScript plugin
Sometimes a server side plugin might come with a client side (JavaScript) plugin, that should be automatically enabled when the server side plugin is enabled.
The $config['Plugins']
variable is a special array that does that.
To enable a plugin, simply add it's name to this array.
$config['Plugins'][] = 'myplugin';
This code is virtually equal to specyfying in config.js:
config.extraPlugins = 'myplugin';
but the advantage of defining it in plugin.php is that it will be enabled only when the server side plugin is also enabled.
Sample plugin: FileSize (adding new server side command - complete example)
Introduction
Probably the best way to learn new things is to write a code, so let's write a plugin that adds a new server side command to the connector. We'll create a command that returns a size of a given file.
The FileSize plugin should provide a new command named "FileSize", in other words, calling:
/ckfinder/core/connector/asp/connector.asp?command=FileSize&type=Files¤tFolder=%2F&fileName=foobar.jpg
(assuming that foobar.jpg exists) should return a valid XML response:
<Connector resourceType="Files">
<Error number="0"/>
<CurrentFolder path="/" url="/ckfinder/userfiles/files/" acl="255"/>
<FileSize size="5647"/>
</Connector>
For the sake of simplicity, we'll first create a simple plugin.asp that just does exactly what we need:
<script runat="server" language="VBScript">
class CKFinder_Connector_CommandHandler_FileSize
'pseudo inheritance
private base
' Since we want to send a XML response, we'll extend the XmlCommandHandlerBase class
Private Sub Class_Initialize()
Set base = new CKFinder_Connector_CommandHandler_XmlCommandHandlerBase
Set base.child = me
End Sub
' Pseudo inheritance
Public Property Get currentFolder()
Set currentFolder = base.currentFolder
End Property
Public Sub sendResponse(response)
base.sendResponse(response)
End sub
Public Property Get ErrorHandler()
Set ErrorHandler = base.ErrorHandler
End Property
' (5) The buildXml method is used to construct an XML response
function buildXml( oXML )
Dim fileName
fileName = request("fileName")
Dim oUFS
Set oUFS = oCKFinder_Factory.UtilsFileSystem
Dim filePath
filePath = oUFS.combinePaths(currentFolder.getServerPath(), fileName)
' (6) Adding a <FileSize> element to the XML response.
Dim size, oNode
size = oUFS.GetFileSize(filePath)
Set oNode = oXML.connectorNode.addChild("FileSize")
oNode.addAttribute "size", size
End function
' Our event listener:
' (3) Register the "FileSize" command
public function onBeforeExecuteCommand( command )
if ( command = "FileSize" ) then
' The sendResponse method is defined in XmlCommandHandlerBase, it creates
' a basic XML response and calls the buildXml()method
sendResponse( response )
' false = stop further execution.
onBeforeExecuteCommand = False
Exit function
End if
onBeforeExecuteCommand = True
End Function
End Class
Dim CommandHandler_FileSize
Set CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize
' Object assigned to a hook must contain event listener named "onEventName"
' (the event name is BeforeExecuteCommand, so we must define an onBeforeExecuteCommand method).
CKFinder_AddHook "BeforeExecuteCommand", CommandHandler_FileSize
CKFinder_AddPlugin "myplugin"
</script>
Step1: Register an event handler
$config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_FileSize, "onBeforeExecuteCommand");
Step2: Create a class
If your plugin returns an XML response, you'll usually just extend the XmlCommandHandlerBase class to reduce the amount of code to write, however it is not a requirement.
// (2) Include base XML command handler
require_once CKFINDER_CONNECTOR_LIB_DIR . "/CommandHandler/XmlCommandHandlerBase.php";
// Since we will send a XML response, we'll extend the XmlCommandHandlerBase
class CKFinder_Connector_CommandHandler_FileSize extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase
Step3: Create an event handler
Our event handler defined in (1) is called "onBeforeExecuteCommand", so let's define such function.
function onBeforeExecuteCommand( &$command )
// ...
Step4: Create the buildXml method
In the onBeforeExecuteCommand
method we have called sendResponse
. The sendResponse method is defined
in XmlCommandHandlerBase class, it creates a basic XML response and calls the buildXml
method, which we need to define.
function buildXml()
// ...
Step5: Construct the XML response
The main task of the buildXml method is to construct an XML response, so we're doing it below:
$oNode = new Ckfinder_Connector_Utils_XmlNode("FileSize");
$oNode->addAttribute("size", $size);
$this->_connectorNode->addChild($oNode);
Full source code
plugin.asp
The full source code of a plugin with all necessary security checks: (save the code as plugin.php in "plugins/myplugin" folder)
<script runat="server" language="VBScript">
class CKFinder_Connector_CommandHandler_FileSize
'pseudo inheritance
private base
' Since we want to send a XML response, we'll extend the XmlCommandHandlerBase class
Private Sub Class_Initialize()
Set base = new CKFinder_Connector_CommandHandler_XmlCommandHandlerBase
Set base.child = me
End Sub
Private Sub Class_Terminate()
Set base.child = Nothing
Set base = Nothing
End Sub
' Pseudo inheritance
Public Property Get currentFolder()
Set currentFolder = base.currentFolder
End Property
Public Sub sendResponse(response)
base.sendResponse(response)
End sub
Public Property Get ErrorHandler()
Set ErrorHandler = base.ErrorHandler
End Property
' (5) The buildXml method is used to construct an XML response
function buildXml( oXML )
if not(currentFolder.checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) then
errorHandler.throwError CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED, "", "ACL check failed"
End if
Dim resourceTypeInfo
Set resourceTypeInfo = currentFolder.getResourceTypeConfig()
Dim fileName
fileName = request("fileName")
If (fileName="") then
errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_NAME, "", "Missing filename"
End if
Dim oUFS
Set oUFS = oCKFinder_Factory.UtilsFileSystem
if (Not oUFS.checkFileName(fileName) or resourceTypeInfo.checkIsHiddenFile(fileName)) then
errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST, "", "Invalid filename"
End if
if (Not resourceTypeInfo.checkExtension(fileName)) then
errorHandler.throwError CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST, "", "Invalid extension"
End if
Dim filePath
filePath = oUFS.combinePaths(currentFolder.getServerPath(), fileName)
If Not(oUFS.fileExists(filePath)) then
errorHandler.throwError CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND, "", "File doesn't exists: " & filePath
End if
' (6) Adding a <FileSize> element to the XML response.
Dim size, oNode
size = oUFS.GetFileSize(filePath)
Set oNode = oXML.connectorNode.addChild("FileSize")
oNode.addAttribute "size", size
End function
' Our event listener:
' (3) Register the "FileSize" command
public function onBeforeExecuteCommand( command )
if ( command = "FileSize" ) then
' The sendResponse method is defined in XmlCommandHandlerBase, it creates
' a basic XML response and calls the buildXml()method
sendResponse( response )
' false = stop further execution.
onBeforeExecuteCommand = False
Exit function
End if
onBeforeExecuteCommand = True
End Function
End Class
Dim CommandHandler_FileSize
If (TypeName(oCKFinder_Factory) <> "Empty") then
Set CommandHandler_FileSize = new CKFinder_Connector_CommandHandler_FileSize
' Object assigned to a hook must contain event listener named "onEventName"
' (the event name is BeforeExecuteCommand, so we must define an onBeforeExecuteCommand method).
CKFinder_AddHook "BeforeExecuteCommand", CommandHandler_FileSize
CKFinder_AddPlugin "myplugin"
End if
</script>
plugin.js
.. and the client side (JavaScript) plugin that will call the FileSize command: (save the code as plugin.js in "plugins/myplugin" folder)
CKFinder.addPlugin( 'myplugin', function( api ) {
api.addFileContextMenuOption( { label : 'File Size', command : "FileSize" } , function( api, file )
{
api.connector.sendCommand( 'FileSize', { fileName : api.getSelectedFile().name }, function( xml )
{
if ( xml.checkError() )
return;
var size = xml.selectSingleNode( 'Connector/FileSize/@size' );
api.openMsgDialog( "", "The exact size of a file is: " + size.value + " bytes");
} );
});
});