View source
<p>If you made it up to here, then we expect you to already have decent understanding about what a synonyms behavior is. This page will try to explain how you could create a new one.</p>
<p>Before I continue further with technical details, let me set certain framework on what synonyms behavior is and where is the line between a behavior and its implementation. Behavior is ultimately an interface that pursuits to deliver some end-user useful functionality. For the sake of example, let's consider the following behavior: whenever an email is sent to a user, our example behavior will swap his/her username in the 1st line of email body with a randomly picked up synonym of that user. This is behavior, because it narrates about behavioral pattern and is abstract to specifics of synonyms storage. Moreover, it sounds reasonable to be declared as a separate behavior (instead of using some pre-existing) because website admin may want to specify from what exact synonyms we can pick up a random nick name upon email being sent.</p>
<p>On the other hand, if you are looking into providing synonyms data to behaviors, i.e. "implementing" behaviors for some specific storage facility, then you are on a wrong page. You better head off to <a href="&topic:synonyms/synonyms_behavior_implementation&">implementing behaviors</a> documentation.</p>
<p>Now that we have cleared the theoretical details, let's get busy with hands on experience. In technical terms synonyms behaviors are just cTools plugins. Synonyms module defines its own plugin type: <em>behavior</em>, which is owned by <em>synonyms</em> module. Throughout writing your own synonyms behavior you can always look into Synonyms module behaviors to get better understanding. You will find the plugins in <em>synonyms/plugins/behavior/*.inc</em> files. If you have never worked before with cTools plugins, it is also worthwhile to check out its <a href="&topic:ctools/plugins-implementing&">documentation</a>.</p>
<p>Your plugin implementation may (or must) have the following keys:</p>
<dt>title</dt>
<dd><b>Required</b> (string) Human-friendly translated title of your behavior.</dd>
<dt>description</dt>
<dd>(string) Human-friendly translated description of your behavior. Include a couple of words about what exactly it does and what end user functionality has.</dd>
<dt>settings form callback</dt>
<dd>(string) Name of a PHP function that will be invoked to generate settings form of your behavior. End user will fill out the form elements and the settings will be saved in the database for your plugin by Synonyms module. If your behavior does not require any additional configuration, you may omit this parameter. If you do require a settings form, then this callback function should receive the following input arguments:<ol>
<li><b>$form</b>: (array) form array into which your settings form elements will be merged. You do not have to change this $form. It is just provided to you in case you want to traverse through it for whatever reason.</li>
<li><b>&$form_state</b>: (array) form state array of the form into which your settings form elements will be merged. Again, you are not obliged to change or to use this argument, but it is provided to you in case you find it useful to keep some data in form state.</li>
<li><b>$settings</b>: (array) array of settings defined for your behavior. This array may be empty, if your behavior hasn't been saved yet, or it may contain previously saved settings. You should use content of this array as default values for your form elements.</li>
</ol>
Based on these input arguments, your settings form callback function should generate form elements array and return it.</dd>
<dt>interface</dt>
<dd><b>Required</b>: (string) Name of a PHP interface that represents your behavior. This interface should declare any methods that support your behavior. Implementations of your behavior will have to implement this interface for a specific storage. To make it easier for you, think of the default synonyms behavior: it introduces the "synonyms" property on entities. Whenever that property is requested, the behavior code loops through enabled behavior implementations asking to "extract synonyms from the storage". So this "extract synonyms" method is declared in the interface. This way behavior implementations can implement the interface and therefore Synonyms without knowing anything specific about the underlying storage will be able to carry out its part - to get a list of synonyms. We advice to name the interfaces in the following fashion: <em>NameOfYourBehaviorHereSynonymsBehavior</em>. Also, your interface must extend the starting point of all synonyms behaviors - the <em>SynonymsBehavior</em> interface. If your behavior depends on functionality provided by other behaviors, then your interface may extend the interface of that behavior.</dd>
<dt>enabled callback</dt>
<dd>(string) Name of a PHP function that will be invoked to notify your behavior that it has just been enabled on a new storage. You could do any set-up routines in this function, if it is required by your behavior. If your behavior does not require any set up logic, you may omit this parameter. If you do specify it, then this callback function should receive the following input arguments:<ol>
<li><b>$behavior_definition</b>: (array) Array of behavior definition. Basically it is your cTools plugin definition.</li>
<li><b>$behavior_implementation</b>: (array) Array of behavior implementation. It will contain various information specific to the storage on which your behavior have just been enabled. Also, behavior implementation, since it is enabled, will contain settings of your behavior which has provided website administrator. You can look up structure of this array in the comments of <em>synonyms_behavior_get()</em> function.</li>
</ol></dd>
<dt>disabled callback</dt>
<dd>(string) Name of a PHP function that will be invoked to notify your behavior that it has just been disabled on a storage. You could do any tear-down routines in this function, if it is required by your behavior. If your behavior does not require any tear down logic, you may omit this parameter. If you do specify it, then this callback function should receive the following input arguments:<ol>
<li><b>$behavior_definition</b>: (array) Array of behavior definition. Basically it is your cTools plugin definition.</li>
<li><b>$behavior_implementation</b>: (array) Array of behavior implementation. It will contain various information specific to the storage on which your behavior have just been disabled. Also, behavior implementation will contain settings of your behavior which has provided website administrator. You can look up structure of this array in the comments of <em>synonyms_behavior_get()</em> function.</li>
</ol></dd>
Having said the above, let us wrap up on how you should create a new behavior:
<ol>
<li>Think through what you want your behavior to do and what interface will be required to support your behavior.</li>
<li>Declare your behavior interface, make sure to document and to well comment the interface methods. The better docs it has, the easier it will be for other developers to implement your behavior for new storage types. Also, make sure your interface extends the necessary interfaces from other behaviors (if your behavior depends on the functionality of other behaviors).</li>
<li>Write PHP code that will use the interface to achieve some productive action. Depending on what your behavior does, it may be but not limited to implementing a hook, writing a custom PHP function, etc. For example, in our dummy "let me swap username with his synonym upon email being sent" case, this would materialize into implementing <em>hook_mail_alter()</em> where you'd have to process email body and swap all occurrences of username with a randomly picked synonym. You will definitely need <em>synonyms_behavior_get()</em> as it allows to load enabled behavior implementations for a given behavior.</li>
<li>Probably you will want to implement your freshly created behavior for at least one storage type. Otherwise your behavior won't have any synonyms to work with and therefore will be useless. Read about implementing a behavior for new storage types <a href="&topic:synonyms/synonyms_behavior_implementation&">here</a>.</li>
</ol>