 exportable objects tool exportable objects are objects that can live either in the database or in code or in both if they live in both then the object in code is considered to be overridden meaning that the version in code is ignored in favor of the version in the database the main benefit to this is that you can move objects that are intended to be structure or featurerelated into code thus removing them entirely from the database this is a very important part of the deployment path since in an ideal world the database is primarily user generated content whereas site structure and site features should be in code however many many features in drupal rely on objects being in the database and provide uis to create them using this system you can give your objects dual life they can be created in the ui exported into code and put in revision control views and panels both use this system heavily plus any object that properly implements this system can be utilized by the features module to be used as part of a bundle of objects that can be turned into feature modules typically exportable objects have two identifiers one identifier is a simple serial used for database identification it is a primary key in the database and can be used locally it also has a name which is an easy way to uniquely identify it this makes it much less likely that importing and exporting these objects across systems will have collisions they still can of course but with good name selection these problems can be worked around making your objects exportable to make your objects exportable you do have to do a medium amount of work create a chunk of code in your object s schema definition in the install file to introduce the object to ctools export system create a load function for your object that utilizes ctoolsexportloadobject create a save function for your object that utilizes drupalwriterecord or any method you desire create an import and export mechanism from the ui the export section of the schema file exportable objects are created by adding definition to the schema in an export section for example function mymoduleschema schema mymodulemyobj array description t table storing myobj definitions export array key name identifier obj exports will be as myobj default hook defaultmymodulemyobj function hook name api array owner mymodule api defaultmymodulemyobjs base name for api include files minimumversion 1 currentversion 1 fields array name array type varchar length 255 description unique id for this object used to identify it programmatically oid array type serial unsigned true not null true description primary id field for the table not used for anything except internal lookups no export true do not export databaseonly keys primary key array oid unique keys array name array name return schema key this is the primary key of the exportable object and should be a string as names are more portable across systems it is possible to use numbers here but be aware that export collisions are very likely defaults to name object the class the object should be created ass defaults as stdclass can disable control whether or not the exportable objects can be disabled all this does is cause the disabled field on the object to always be set appropriately and a variable is kept to record the state changes made to this state must be handled by the owner of the object defaults to true status exportable objects can be enabled or disabled and this status is stored in a variable this defines what variable that is defaults to default table default hook what hook to invoke to find exportable objects that are currently defined these will all be gathered into a giant array defaults to default table identifier when exporting the object the identifier is the variable that the exported object will be placed in defaults to table bulk export declares whether or not the exportable will be available for bulk exporting bulk export ui is currently left to be handled by contrib though the core hooks are present so this can be done export callback the callback to use for bulk exporting defaults to module export table this function will receive the myobject and indent as arguments list callback bulk export callback to provide a list of exportable objects to be chosen for bulk exporting defaults to module table list to hook code callback function used to generate an export for the bulk export process this is only necessary if the export is more complicated than simply listing the fields defaults to module table tohookcode in addition each field can contain the following no export set to true to prevent that field from being exported export callback a function to override the export behavior it will receive myobject field value indent as arguments by default fields are exported through ctoolsvarexport  reserved keys on exportable objects exportable objects have several reserved keys that are used by the ctools export api each key can be found at myobj key on an object loaded through ctoolsexportloadobject implementing modules should not use these keys as they will be overwritten by the ctools export api apiversion the api version that this object implements disabled a boolean for whether the object is disabled exportmodule for objects that live in code the module which provides the default object exporttype a bitmask representation of an object current storage you can use this bitmask in combination with the exportincode and exportindatabase constants to test for an object s storage in your code incodeonly a boolean for whether the object lives only in code table the schema api table that this object belongs to type a string representing the storage type of this object can be one of the following  normal is an object that lives only in the database overridden is an object that lives in the database and is overriding the exported configuration of a corresponding object in code default is an object that lives only in code the load function typically there will be two load functions a single load to load just one object and an all load to load all of the objects for use in administrating the objects or utilizing the objects when you need all of them using ctoolsexportloadobject you can easily do both as well as quite a bit in between this example shows loading just one object load a single myobj function mymodulemyobjload name ctoolsinclude export result ctoolsexportloadobject mymodulemyobjs names array name if isset result name return result name  the save function the export mechanism does not actually provide a method to save an object this is okay because in the simple case drupalwriterecord does the job well in the more complex cases it would not work for you anyway load a single myobj function mymodulemyobjsave myobj update isset myobj oid isnumeric myobj oid array oid array drupalwriterecord myobj myobj update  export from the ui in your hookmenu you should define a path where users can export your object object in our example below this is admin build mymodule export where the matches our myobj s unique identifier this identifier will be passed to a form called mymoduleexportmyobj implementation of hookmenu function mymodulemenu items admin build mymodule export array title export page callback mymoduleexportmyobj page arguments array 3 access arguments array mymodule export permission type menucallback return items export a myobj and display it in a form function mymoduleexportmyobj formstate oid myobj mymodulemyobjload oid drupalsettitle checkplain myobj description code mymodulemyobjexport myobj return drupalgetform ctoolsexportform code checkplain myobj description the mymoduleexportmyobj form function calls two functions mymodulemyobjload to fetch the object in the desired format and mymodulemyobjexport to generate the exportable load a single myobj function mymodulemyobjload oid ctoolsinclude export result ctoolsexportloadobject mymodulemyobjs names array oid if isset result oid return result oid export a myobj by declaring this function in the schema anyone can easily export a myobj just by knowing that myobj exists function mymodulemyobjexport myobj indent ctoolsinclude export output ctoolsexportobject mymodulemyobjs myobj indent return output  import from the ui please note importing objects means you let the user run php code do not give this permission to untrusted users much like with exporting you ll need a menu entry to handle the import implementation of hookmenu function mymodulemenu items admin build mymodule import array title import page callback drupalgetform page arguments array mymoduleexportmyobj access arguments array mymodule import permission type menucallback return items in this case the page callback is a form where the user can paste the exported code we can provide an optional name field to change the name of the object while importing this can be used as a poor man s clone the method used here can also be used to very easily clone objects without going through the export import process manually form from page callback to import a myobj function mymoduleexportmyobj form formstate form name array type textfield title t myobj name description t enter the name of the new myobj this is optional and is not necessary if you do not wish to rename the object form object array type textarea title t paste variant code here rows 15 make sure that an import actually provides a handler function mymoduleexportmyobjvalidate form formstate first run the php and turn the input code into an object obstart eval formstate values object obendclean the object should appear as myobj this was the identifier set in the export section of the schema if empty myobj errors obgetcontents if empty errors errors t no myobj found formerror form object t unable to get a myobj from the import errors reported errors array errors errors formstate obj obj save the imported object function pagemanagerhandlerimportsubmit form formstate myobj formstate obj if empty formstate values name myobj name formstate values name mymodulemyobjsave myobj formstate redirect admin build mymodule myobj name edit  enabling and disabling exported objects exportable objects can be enabled or disabled by default the status of exported objects are stored in a variable defined in the export section of your hookschema the variable is an array with object primary keys and their corresponding status as a boolean where true means disabled and false means enabled  for the following status variable array apples true bananas true oranges false the apples and bananas objects are disabled while oranges is enabled this convention ensures that objects are enabled by default until they have an entry in the status variable that says otherwise you can enable or disable objects using the ctools export api disable an object by name objectname oranges ctoolsinclude export ctoolsexportsetstatus myobj oranges enable an object by name ctoolsexportsetstatus myobj oranges false disable a loaded object object mymodulemyobjload apples ctoolsexportsetobjectstatus object enable a loaded object ctoolsexportsetobjectstatus object false an object s status will be set by ctoolsexportloadobject at myobj disabled note that the actual meaning of the myobj disabled flag is delegated to the implementing module it is your responsibility to include exclude disabled objects from appearing on administrative forms being editable and exhibiting their general behavior putting exported objects into code this section still needs to be written  