[GENERIC] Zend_Translate:
[zend.git] / documentation / manual / en / module_specs / Zend_Tool-Extending.xml
blob7b1d3bacd8836b79e1d83eed597ffb8629105fc9
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.tool.extending">
4     <title>Extending Zend_Tool</title>
6     <sect2 id="zend.tool.extending.overview">
7         <title>Overview of Zend_Tool</title>
9         <para>
10             <classname>Zend_Tool_Framework</classname> is a framework for exposing common
11             functionalities such as the creation of project scaffolds, code
12             generation, search index generation, and much more. Functionality may be
13             written and exposed via <acronym>PHP</acronym> classes dropped into the
14             <acronym>PHP</acronym> <property>include_path</property>, providing incredible
15             flexibility of implementation. The functionality may then be consumed by writing
16             implementation and/or protocol-specific clients -- such as console
17             clients, <acronym>XML-RPC</acronym>, <acronym>SOAP</acronym>, and much more.
18         </para>
20         <para>
21             <classname>Zend_Tool_Project</classname> builds on and extends the capabilities of
22             <classname>Zend_Tool_Framework</classname> to that of managing a "project". In general,
23             a "project" is a planned endeavor or an initiative. In the computer world, projects
24             generally are a collection of resources. These resources can be files, directories,
25             databases, schemas, images, styles, and more.
26         </para>
27     </sect2>
29     <sect2 id="zend.tool.extending.zend-tool-framework">
30         <title>Zend_Tool_Framework Extensions</title>
32         <sect3 id="zend.tool.extending.zend-tool-framework.architecture">
33             <title>Overall Architecture</title>
35             <para>
36                 <classname>Zend_Tool_Framework</classname> provides the following:
37             </para>
39             <itemizedlist>
40                 <listitem>
41                     <para>
42                         <emphasis>Common interfaces and abstracts</emphasis> that allow
43                         developers to create functionality and capabilities that are
44                         dispatchable by tooling clients.
45                     </para>
46                 </listitem>
48                 <listitem>
49                     <para>
50                         <emphasis>Base client functionality</emphasis> and a concrete
51                         console implementation that connect external tools and
52                         interfaces to the <classname>Zend_Tool_Framework</classname>. The Console
53                         client may be used in <acronym>CLI</acronym> environments such as unix
54                         shells and the Windows console.
55                     </para>
56                 </listitem>
58                 <listitem>
59                     <para>
60                         <emphasis>"Provider" and "Manifest" interfaces</emphasis> that
61                         can be utilized by the tooling system. "Providers" represent the
62                         functional aspect of the framework, and define the actions that
63                         tooling clients may call. "Manifests" act as metadata registries
64                         that provide additional context for the various defined
65                         providers.
66                     </para>
67                 </listitem>
69                 <listitem>
70                     <para>
71                         <emphasis>An introspective loading system</emphasis> that will
72                         scan the environment for providers and determine what is
73                         required to dispatch them.
74                     </para>
75                 </listitem>
77                 <listitem>
78                     <para>
79                         <emphasis>A standard set of system providers</emphasis> that
80                         allow the system to report what the full capabilities of the
81                         system are as well as provide useful feedback. This also
82                         includes a comprehensive "Help System".
83                     </para>
84                 </listitem>
85             </itemizedlist>
87             <para>
88                 Definitions that you should be aware of through this manual with respect
89                 to <classname>Zend_Tool_Framework</classname> include:
90             </para>
92             <itemizedlist>
93                 <listitem>
94                     <para>
95                         <classname>Zend_Tool_Framework</classname> - The framework which exposes
96                         tooling capabilities.
97                     </para>
98                 </listitem>
100                 <listitem>
101                     <para>
102                         <emphasis>Tooling Client</emphasis> - A developer tool that connects
103                         to and consumes <classname>Zend_Tool_Framework</classname>.
104                     </para>
105                 </listitem>
107                 <listitem>
108                     <para>
109                         <emphasis>Client</emphasis> - The subsystem of
110                         <classname>Zend_Tool_Framework</classname> that exposes an interface such
111                         that tooling clients can connect, query and execute commands.
112                     </para>
113                 </listitem>
115                 <listitem>
116                     <para>
117                         <emphasis>Console Client / Command Line Interface /
118                         <filename>zf.php</filename></emphasis> - The tooling client for the command
119                         line. </para>
120                 </listitem>
122                 <listitem>
123                     <para>
124                         <emphasis>Provider</emphasis> - A subsystem and a collection of
125                         built-in functionality that the framework exports.
126                     </para>
127                 </listitem>
129                 <listitem>
130                     <para>
131                         <emphasis>Manifest</emphasis> - A subsystem for defining,
132                         organizing, and disseminating provider requirement data.
133                     </para>
134                 </listitem>
136                 <listitem>
137                     <para>
138                         <classname>Zend_Tool_Project</classname> Provider - A set of providers
139                         specifically for creating and maintaining Zend Framework-based
140                         projects.
141                     </para>
142                 </listitem>
143             </itemizedlist>
144         </sect3>
146         <sect3 id="zend.tool.extending.zend-tool-framework.cli-client">
147             <title>Understanding the CLI Client</title>
149             <para>
150                 The <acronym>CLI</acronym>, or command line tool (internally known as the console
151                 tool), is currently the primary interface for dispatching
152                 <classname>Zend_Tool</classname> requests. With the <acronym>CLI</acronym> tool,
153                 developers can issue tooling requests inside the "command line windows", also
154                 commonly known as a "terminal" window. This environment is predominant in the *nix
155                 environment, but also has a common implementation in windows with the
156                 <filename>cmd.exe</filename>, console2 and also with the Cygwin project.
157             </para>
159             <sect4 id="zend.tool.extending.zend-tool-framework.cli-client.setup-general">
160                 <title>Setting up the CLI tool</title>
162                 <para>
163                     To issue tooling requests via the command line client, you first
164                     need to set up the client so that your system can handle the "zf"
165                     command. The command line client, for all intents and purposes, is
166                     the <filename>.sh</filename> or <filename>.bat</filename> file that is provided
167                     with your Zend Framework distribution. In trunk, it can be found here:
168                     <ulink
169                         url="http://framework.zend.com/svn/framework/standard/trunk/bin/">http://framework.zend.com/svn/framework/standard/trunk/bin/</ulink>.
170                 </para>
172                 <para>
173                     As you can see, there are 3 files in the <filename>/bin/</filename>
174                     directory: a <filename>zf.php</filename>, <filename>zf.sh</filename>, and
175                     <filename>zf.bat</filename>. The <filename>zf.sh</filename> and the
176                     <filename>zf.bat</filename> are the operating system specific client
177                     wrappers: <filename>zf.sh</filename> for the *nix environment, and
178                     <filename>zf.bat</filename> for the Win32 environment. These client wrappers are
179                     responsible for finding the proper <filename>php.exe</filename>, finding the
180                     <filename>zf.php</filename>, and passing on the client request. The
181                     <filename>zf.php</filename> is the responsible for handling understanding
182                     your environment, constructing the proper include_path, and passing
183                     what is provided on the command line to the proper library component
184                     for dispatching.
185                 </para>
187                 <para>
188                     Ultimately, you want to ensure two things to make everything work
189                     regardless of the operating system you are on:
190                 </para>
192                 <orderedlist>
193                     <listitem>
194                         <para>
195                             <filename>zf.sh/zf.bat</filename> is reachable from your system
196                             path. This is the ability to call <command>zf</command> from
197                             anywhere on your command line, regardless of what your
198                             current working directory is.
199                         </para>
200                     </listitem>
202                     <listitem>
203                         <para>
204                             <filename>ZendFramework/library</filename> is in your
205                             <property>include_path</property>.
206                         </para>
207                     </listitem>
208                 </orderedlist>
210                 <note>
211                     <para>
212                         Note: while the above are the most ideal
213                         requirements, you can simply download Zend Framework and expect it
214                         to work as <filename>./path/to/zf.php</filename> some command.
215                     </para>
216                 </note>
217             </sect4>
219             <sect4 id="zend.tool.extending.zend-tool-framework.cli-client.setup-starnix">
220                 <title>Setting up the CLI tool on Unix-like Systems</title>
222                 <para>
223                     The most common setup in the *nix environment, is to copy the
224                     <filename>zf.sh</filename> and <filename>zf.php</filename> into the same
225                     directory as your <acronym>PHP</acronym> binary. This can generally be found in
226                     one of the following places:
227                 </para>
229                 <programlisting language="text"><![CDATA[
230 /usr/bin
231 /usr/local/bin
232 /usr/local/ZendServer/bin/
233 /Applications/ZendServer/bin/
234 ]]></programlisting>
236                 <para>
237                     To find out the location of your <acronym>PHP</acronym> binary, you can execute
238                     'which php' on the command line. This will return the location of the
239                     <acronym>PHP</acronym> binary you will be using to run <acronym>PHP</acronym>
240                     scripts in this environment.
241                 </para>
243                 <para>
244                     The next order of business is to ensure that Zend Framework
245                     library is set up correctly inside of the system <acronym>PHP</acronym>
246                     <property>include_path</property>. To find out where your
247                     <property>include_path</property> is located, you can execute
248                     <command>php -i</command> and look for the <property>include_path</property>
249                     variable, or more succinctly, execute
250                     <command>php -i | grep include_path</command>. Once you have found where
251                     your <property>include_path</property> is located (this will generally be
252                     something like <filename>/usr/lib/php</filename>,
253                     <filename>/usr/share/php</filename>, <filename>/usr/local/lib/php</filename>, or
254                     similar), ensure that the contents of the <filename>/library/</filename>
255                     directory are put inside your <property>include_path</property> specified
256                     directory.
257                 </para>
259                 <para>
260                     Once you have done those two things, you should be able to issue a
261                     command and get back the proper response like this:
262                 </para>
264                 <para>
265                     <inlinegraphic scale="100" align="center" valign="middle"
266                         fileref="figures/zend.tool.framework.cliversionunix.png" format="PNG" />
267                 </para>
269                 <para>
270                     If you do not see this type of output, go back and check your setup
271                     to ensure you have all of the necessary pieces in the proper place.
272                 </para>
274                 <para>
275                     There are a couple of alternative setups you might want to employ
276                     depending on your servers configuration, your level of access, or
277                     for other reasons.
278                 </para>
280                 <para>
281                     <emphasis>Alternative Setup</emphasis> involves keeping the Zend
282                     Framework download together as is, and creating a link from a
283                     <constant>PATH</constant> location to the <filename>zf.sh</filename>. What this
284                     means is you can place the contents of the ZendFramework download into a
285                     location such as <filename>/usr/local/share/ZendFramework</filename>, or more
286                     locally like <filename>/home/username/lib/ZendFramework</filename>, and creating
287                     a symbolic link to the <filename>zf.sh</filename>.
288                 </para>
290                 <para>
291                     Assuming you want to put the link inside <filename>/usr/local/bin</filename>
292                     (this could also work for placing the link inside
293                     <filename>/home/username/bin/</filename> for example) you would issue a
294                     command similar to this:
295                 </para>
297                 <programlisting language="sh"><![CDATA[
298 ln -s /usr/local/share/ZendFramework/bin/zf.sh /usr/local/bin/zf
300 # OR (for example)
301 ln -s /home/username/lib/ZendFramework/bin/zf.sh /home/username/bin/zf
302 ]]></programlisting>
304                 <para>
305                     This will create a link which you should be able to access globally
306                     on the command line.
307                 </para>
308             </sect4>
310             <sect4 id="zend.tool.extending.zend-tool-framework.cli-client.setup-windows">
311                 <title>Setting up the CLI tool on Windows</title>
313                 <para>
314                     The most common setup in the Windows Win32 environment, is to copy
315                     the <filename>zf.bat</filename> and <filename>zf.php</filename> into the same
316                     directory as your <acronym>PHP</acronym> binary. This can generally be found in
317                     one of the following places:
318                 </para>
320                 <programlisting language="text"><![CDATA[
321 C:\PHP
322 C:\Program Files\ZendServer\bin\
323 C:\WAMP\PHP\bin
324 ]]></programlisting>
326                 <para>
327                     You should be able to run <filename>php.exe</filename> on the command line.
328                     If you are not able to, first check the documentation that came with
329                     your <acronym>PHP</acronym> distribution, or ensure that the path to
330                     <filename>php.exe</filename> is in your
331                     Windows <constant>PATH</constant> environment variable.
332                 </para>
334                 <para>
335                     The next order of business is to ensure that Zend Framework
336                     library is set up correctly inside of the system <acronym>PHP</acronym>
337                     <property>include_path</property>. To find out where your
338                     <property>include_path</property> is located, you can type
339                     <command>php -i</command> and look for the <property>include_path</property>
340                     variable, or more succinctly execute
341                     <command>php -i | grep include_path</command> if you have Cygwin setup with
342                     grep available. Once you have found where your
343                     <property>include_path</property> is located (this will generally be
344                     something like <filename>C:\PHP\pear</filename>,
345                     <filename>C:\PHP\share</filename>,
346                     <filename>C:\Program%20Files\ZendServer\share</filename> or similar), ensure
347                     that the contents of the library/ directory are put inside your
348                     <property>include_path</property> specified directory.
349                 </para>
351                 <para>
352                     Once you have done those two things, you should be able to issue a
353                     command and get back the proper response like this:
354                 </para>
356                 <para>
357                     <inlinegraphic scale="100" align="center" valign="middle"
358                         fileref="figures/zend.tool.framework.cliversionwin32.png" format="PNG" />
359                 </para>
361                 <para>
362                     If you do not see this type of output, go back and check your setup
363                     to ensure you have all of the necessary pieces in the proper place.
364                 </para>
366                 <para>
367                     There are a couple of alternative setups you might want to employ
368                     depending on your server's configuration, your level of access, or
369                     for other reasons.
370                 </para>
372                 <para>
373                     <emphasis>Alternative Setup</emphasis> involves keeping the Zend
374                     Framework download together as is, and altering both your system
375                     <constant>PATH</constant> as well as the <filename>php.ini</filename> file.
376                     In your user's environment, make sure to add
377                     <filename>C:\Path\To\ZendFramework\bin</filename>, so that your
378                     <filename>zf.bat</filename> file is executable. Also, alter the
379                     <filename>php.ini</filename> file to ensure that
380                     <filename>C:\Path\To\ZendFramework\library</filename> is in your
381                     <property>include_path</property>.
382                 </para>
383             </sect4>
385             <sect4 id="zend.tool.extending.zend-tool-framework.cli-client.setup-othernotes">
386                 <title>Other Setup Considerations</title>
388                 <para>
389                     If for some reason you do not want Zend Framework library inside
390                     your <property>include_path</property>, there is another option. There are
391                     two special environment variables that <filename>zf.php</filename> will
392                     utilize to determine the location of your Zend Framework
393                     installation.
394                 </para>
396                 <para>
397                     The first is <constant>ZEND_TOOL_INCLUDE_PATH_PREPEND</constant>, which will
398                     prepend the value of this environment variable to the system
399                     (<filename>php.ini</filename>) <property>include_path</property> before loading
400                     the client.
401                 </para>
403                 <para>
404                     Alternatively, you might want to use
405                     <constant>ZEND_TOOL_INCLUDE_PATH</constant> to completely
406                     <emphasis>replace</emphasis> the system <property>include_path</property>
407                     for one that makes sense specifically for the <command>zf</command>
408                     command line tool.
409                 </para>
410             </sect4>
411         </sect3>
413         <sect3 id="zend.tool.extending.zend-tool-framework.providers-and-manifests">
414             <title>Creating Providers</title>
416             <para>
417                 In general, a provider, on its own, is nothing more than the shell for a
418                 developer to bundle up some capabilities they wish to dispatch with the
419                 command line (or other) clients. It is an analogue to what a
420                 "controller" is inside of your <acronym>MVC</acronym> application.
421             </para>
423             <sect4 id="zend.tool.extending.zend-tool-framework.providers-and-manifests.loading">
424                 <title>How Zend_Tool finds your Providers</title>
426                 <para>
427                     By default <classname>Zend_Tool</classname> uses the BasicLoader to find all
428                     the providers that you can run. It recursivly iterates all
429                     include path directories and opens all files that end
430                     with "Manifest.php" or "Provider.php". All classes in these
431                     files are inspected if they implement either
432                     <classname>Zend_Tool_Framework_Provider_Interface</classname>
433                     or <classname>Zend_Tool_Framework_Manifest_ProviderManifestable</classname>.
434                     Instances of the provider interface make up for the real functionality
435                     and all their public methods are accessible as provider actions.
436                     The ProviderManifestable interface however requires the implementation of a
437                     method <methodname>getProviders()</methodname> which returns an array of
438                     instantiated provider interface instances.
439                 </para>
441                 <para>
442                     The following naming rules apply on how you can access the providers
443                     that were found by the IncludePathLoader:
444                 </para>
446                 <itemizedlist>
447                     <listitem>
448                         <para>
449                             The last part of your classname split by underscore is used
450                             for the provider name, e.g. "My_Provider_Hello" leads to your
451                             provider being accessible by the name "hello".
452                         </para>
453                     </listitem>
455                     <listitem>
456                         <para>
457                             If your provider has a method <methodname>getName()</methodname>
458                             it will be used instead of the previous method to determine
459                             the name.
460                         </para>
461                     </listitem>
463                     <listitem>
464                         <para>
465                             If your provider has "Provider" as prefix, e.g. it is called
466                             <classname>My_HelloProvider</classname> it will be stripped
467                             from the name so that the provider will be called "hello".
468                         </para>
469                     </listitem>
470                 </itemizedlist>
472                 <note>
473                     <para>The IncludePathLoader does not follow symlinks, that means
474                     you cannot link provider functionality into your include paths,
475                     they have to be physically present in the include paths.</para>
476                 </note>
478                 <example
479                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.loading.example">
480                     <title>Exposing Your Providers with a Manifest</title>
482                     <para>
483                         You can expose your providers to <classname>Zend_Tool</classname> by
484                         offering a manifest with a special filename ending with "Manifest.php".
485                         A Provider Manifest is an implementation of the
486                         <interface>Zend_Tool_Framework_Manifest_ProviderManifestable</interface>
487                         and requires the <methodname>getProviders()</methodname> method to return
488                         an array of instantiated providers. In anticipation of our first
489                         own provider <classname>My_Component_HelloProvider</classname>
490                         we will create the following manifest:
491                     </para>
493                     <programlisting language="php"><![CDATA[
494 class My_Component_Manifest
495     implements Zend_Tool_Framework_Manifest_ProviderManifestable
497     public function getProviders()
498     {
499         return array(
500             new My_Component_HelloProvider()
501         );
502     }
504 ]]></programlisting>
505                 </example>
506             </sect4>
508             <sect4 id="zend.tool.extending.zend-tool-framework.providers-and-manifests.basic">
509                 <title>Basic Instructions for Creating Providers</title>
511                 <para>
512                     As an example, if a developer wants to add the capability of showing
513                     the version of a datafile that his 3rd party component is working
514                     from, there is only one class the developer would need to implement.
515                     Assuming the component is called <classname>My_Component</classname>, he would
516                     create a class named <classname>My_Component_HelloProvider</classname> in a
517                     file named <filename>HelloProvider.php</filename> somewhere on the
518                     <property>include_path</property>. This class would implement
519                     <classname>Zend_Tool_Framework_Provider_Interface</classname>, and the body of
520                     this file would only have to look like the following:
521                 </para>
523                 <programlisting language="php"><![CDATA[
524 class My_Component_HelloProvider
525     implements Zend_Tool_Framework_Provider_Interface
527     public function say()
528     {
529         echo 'Hello from my provider!';
530     }
532 ]]></programlisting>
534                 <para>
535                     Given that code above, and assuming the developer wishes to access
536                     this functionality through the console client, the call would look
537                     like this:
538                 </para>
540                 <programlisting language="sh"><![CDATA[
541 % zf say hello
542 Hello from my provider!
543 ]]></programlisting>
544             </sect4>
546             <sect4 id="zend.tool.extending.zend-tool-framework.providers-and-manifests.response">
547                 <title>The response object</title>
549                 <para>
550                     As discussed in the architecture section <classname>Zend_Tool</classname> allows
551                     to hook different clients for using your <classname>Zend_Tool</classname>
552                     providers. To keep compliant with different clients you should use the response
553                     object to return messages from your providers instead of using
554                     <methodname>echo()</methodname> or a similiar output mechanism. Rewritting our
555                     hello provider with this knowledge it looks like:
556                 </para>
558                 <programlisting language="php"><![CDATA[
559 class My_Component_HelloProvider
560     extends Zend_Tool_Framework_Provider_Abstract
562     public function say()
563     {
564         $this->_registry->getResponse
565                         ->appendContent("Hello from my provider!");
566     }
568 ]]></programlisting>
570                 <para>
571                     As you can see one has to extend the
572                     <classname>Zend_Tool_Framework_Provider_Abstract</classname> to gain access to
573                     the Registry which holds the
574                     <classname>Zend_Tool_Framework_Client_Response</classname> instance.
575                 </para>
576             </sect4>
578             <sect4 id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced">
579                 <title>Advanced Development Information</title>
581                 <sect5
582                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced.variables">
583                     <title>Passing Variables to a Provider</title>
585                     <para>
586                         The above "Hello World" example is great for simple commands, but
587                         what about something more advanced? As your scripting and tooling
588                         needs grow, you might find that you need the ability to accept
589                         variables. Much like function signatures have parameters, your
590                         tooling requests can also accept parameters.
591                     </para>
593                     <para>
594                         Just as each tooling request can be isolated to a method within a
595                         class, the parameters of a tooling request can also be isolated in a
596                         very well known place. Parameters of the action methods of a
597                         provider can include the same parameters you want your client to
598                         utilize when calling that provider and action combination. For
599                         example, if you wanted to accept a name in the above example, you
600                         would probably do this in OO code:
601                     </para>
603                     <programlisting language="php"><![CDATA[
604 class My_Component_HelloProvider
605     implements Zend_Tool_Framework_Provider_Interface
607     public function say($name = 'Ralph')
608     {
609         echo 'Hello' . $name . ', from my provider!';
610     }
612 ]]></programlisting>
614                     <para>
615                         The above example can then be called via the command line
616                         <command>zf say hello Joe</command>. "Joe" will be supplied to the provider
617                         as a parameter of the method call. Also note, as you see that the
618                         parameter is optional, that means it is also optional on the command
619                         line, so that <command>zf say hello</command> will still work, and default
620                         to the name "Ralph".
621                     </para>
622                 </sect5>
624                 <sect5
625                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced.prompt">
626                     <title>Prompt the User for Input</title>
628                     <para>
629                         There are cases when the workflow of your provider requires
630                         to prompt the user for input. This can be done by requesting
631                         the client to ask for more the required input by calling:
632                     </para>
634                     <programlisting language="php"><![CDATA[
635 class My_Component_HelloProvider
636     extends Zend_Tool_Framework_Provider_Abstract
638     public function say($name = 'Ralph')
639     {
640         $nameResponse = $this->_registry
641                              ->getClient()
642                              ->promptInteractiveInput("Whats your name?");
643         $name = $name->getContent();
645         echo 'Hello' . $name . ', from my provider!';
646     }
648 ]]></programlisting>
650                     <para>
651                         This command throws an exception if the current client is not
652                         able to handle interactive requests. In case of the default Console Client
653                         however you will be asked to enter the name.
654                     </para>
655                 </sect5>
657                 <sect5
658                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced.pretendable">
659                     <title>Pretending to execute a Provider Action</title>
661                     <para>
662                         Another interesting feature you might wish to implement is
663                         <emphasis>pretendability</emphasis>. Pretendabilty is the ability
664                         for your provider to "pretend" as if it is doing the requested
665                         action and provider combination and give the user as much
666                         information about what it <emphasis>would</emphasis> do without
667                         actually doing it. This might be an important notion when doing
668                         heavy database or filesystem modifications that the user might not
669                         otherwise want to do.
670                     </para>
672                     <para>
673                         Pretendability is easy to implement. There are two parts to this
674                         feature: 1) marking the provider as having the ability to "pretend",
675                         and 2) checking the request to ensure the current request was indeed
676                         asked to be "pretended". This feature is demonstrated in the code
677                         sample below.
678                     </para>
680                     <programlisting language="php"><![CDATA[
681 class My_Component_HelloProvider
682     extends    Zend_Tool_Framework_Provider_Abstract
683     implements Zend_Tool_Framework_Provider_Pretendable
685     public function say($name = 'Ralph')
686     {
687         if ($this->_registry->getRequest()->isPretend()) {
688             echo 'I would say hello to ' . $name . '.';
689         } else {
690             echo 'Hello' . $name . ', from my provider!';
691         }
692     }
694 ]]></programlisting>
696                     <para>
697                         To run the provider in pretend mode just call:
698                     </para>
700                     <programlisting language="sh"><![CDATA[
701 % zf --pretend say hello Ralph
702 I would say hello Ralph.
703 ]]></programlisting>
704                 </sect5>
706                 <sect5
707                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced.verbosedebug">
708                     <title>Verbose and Debug modes</title>
710                     <para>
711                         You can also run your provider actions in "verbose" or "debug" modes.
712                         The semantics in regard to this actions have to be implemented by you
713                         in the context of your provider. You can access debug or verbose modes
714                         with:
715                     </para>
717                     <programlisting language="php"><![CDATA[
718 class My_Component_HelloProvider
719     implements Zend_Tool_Framework_Provider_Interface
721     public function say($name = 'Ralph')
722     {
723         if($this->_registry->getRequest()->isVerbose()) {
724             echo "Hello::say has been called\n";
725         }
726         if($this->_registry->getRequest()->isDebug()) {
727             syslog(LOG_INFO, "Hello::say has been called\n");
728         }
729     }
731 ]]></programlisting>
732                 </sect5>
734                 <sect5
735                     id="zend.tool.extending.zend-tool-framework.providers-and-manifests.advanced.configstorage">
736                     <title>Accessing User Config and Storage</title>
738                     <para>
739                         Using the Enviroment variable <property>ZF_CONFIG_FILE</property> or the
740                         .zf.ini in your home directory you can inject configuration parameters into
741                         any <classname>Zend_Tool</classname> provider. Access to this configuration
742                         is available via the registry that is passed to your provider if you extend
743                         <classname>Zend_Tool_Framework_Provider_Abstract</classname>.
744                     </para>
746                     <programlisting language="php"><![CDATA[
747 class My_Component_HelloProvider
748     extends Zend_Tool_Framework_Provider_Abstract
750     public function say()
751     {
752         $username = $this->_registry->getConfig()->username;
753         if(!empty($username)) {
754             echo "Hello $username!";
755         } else {
756             echo "Hello!";
757         }
758     }
760 ]]></programlisting>
762                     <para>
763                         The returned configuration is of the type
764                         <classname>Zend_Tool_Framework_Client_Config</classname> but internally the
765                         <methodname>__get()</methodname> and <methodname>__set()</methodname> magic
766                         methods proxy to a <classname>Zend_Config</classname> of the given
767                         configuration type.
768                     </para>
770                     <para>
771                         The storage allows to save arbitrary data for later reference. This can be
772                         useful for batch processing tasks or for re-runs of your tasks. You can
773                         access the storage in a similar way like the configuration:
774                     </para>
776                     <programlisting language="php"><![CDATA[
777 class My_Component_HelloProvider
778     extends Zend_Tool_Framework_Provider_Abstract
780     public function say()
781     {
782         $aValue = $this->_registry->getStorage()->get("myUsername");
783         echo "Hello $aValue!";
784     }
786 ]]></programlisting>
788                     <para>
789                         The <acronym>API</acronym> of the storage is very simple:
790                     </para>
792                     <programlisting language="php"><![CDATA[
793 class Zend_Tool_Framework_Client_Storage
795     public function setAdapter($adapter);
796     public function isEnabled();
797     public function put($name, $value);
798     public function get($name, $defaultValue=null);
799     public function has($name);
800     public function remove($name);
801     public function getStreamUri($name);
803 ]]></programlisting>
805                     <important>
806                         <para>
807                             When designing your providers that are config or storage aware remember
808                             to check if the required user-config or storage keys really exist for a
809                             user. You won't run into fatal errors when none of these are provided
810                             though, since empty ones are created upon request.
811                         </para>
812                     </important>
813                 </sect5>
814             </sect4>
815         </sect3>
816     </sect2>
818     <sect2 id="zend.tool.extending.zend-tool-project">
819         <title>Zend_Tool_Project Extensions</title>
821         <para>
822             <classname>Zend_Tool_Project</classname> exposes a rich set of functionality and
823             capabilities that make the task of creating new providers, specficially those targetting
824             project easier and more manageable.
825         </para>
827         <sect3 id="zend.tool.extending.zend-tool-project.architecture">
828             <title>Overall Architecture</title>
830             <para>
831                 This same concept applies to Zend Framework projects. In Zend Framework projects,
832                 you have controllers, actions, views, models, databases and so on and so forth. In
833                 terms of <classname>Zend_Tool</classname>, we need a way to track these types of
834                 resources - thus <classname>Zend_Tool_Project</classname>.
835             </para>
837             <para>
838                 <classname>Zend_Tool_Project</classname> is capable of tracking project resources
839                 throughout the development of a project. So, for example, if in one command you
840                 created a controller, and in the next command you wish to create an action within
841                 that controller, <classname>Zend_Tool_Project</classname> is gonna have to
842                 <emphasis>know</emphasis> about the controller file you created so that you can (in
843                 the next action), be able to append that action to it. This is what keeps our
844                 projects up to date and <emphasis>stateful</emphasis>.
845             </para>
847             <para>
848                 Another important point to understand about projects is that typically, resources
849                 are organized in a hierarchical fashion. With that in mind,
850                 <classname>Zend_Tool_Project</classname> is capable of serializing the current
851                 project into a internal representation that allows it to keep track of not only
852                 <emphasis>what</emphasis> resources are part of a project at any given time, but
853                 also <emphasis>where</emphasis> they are in relation to one another.
854             </para>
855         </sect3>
858         <sect3 id="zend.tool.extending.zend-tool-project.providers">
859             <title>Creating Providers</title>
861             <para>
862                 Project specific providers are created in the same fashion as plain framework
863                 providers, with one exception: project providers must extend the
864                 <code>Zend_Tool_Project_Provider_Abstract</code>. This class comes with some
865                 significant functionality that helps developers load existing project, obtian the
866                 profile object, and be able to search the profile, then later store any changes to
867                 the current project profile.
868             </para>
870             <programlisting language="php"><![CDATA[
871 class My_Component_HelloProvider
872     extends Zend_Tool_Project_Provider_Abstract
874     public function say()
875     {
876         $profile = $this->_loadExistingProfile();
878         /* ... do project stuff here */
880         $this->_storeProfile();
881     }
883 ]]></programlisting>
884         </sect3>
886         <!--
887         <sect3 id="zend.tool.extending.zend-tool-project.resources-and-contexts">
888             <title>Creating Resources &amp; Contexts</title>
892         </sect3>
893         -->
894     </sect2>
895 </sect1>