Build That Phing!

  • 535 views
Uploaded on

PHPMD, PHPCS, PHPUnit and PHPLint; these are all tools to maintain code quality. Executing these tasks is a chore and there are many ways to automate this process, Phing being one of them. The goal of …

PHPMD, PHPCS, PHPUnit and PHPLint; these are all tools to maintain code quality. Executing these tasks is a chore and there are many ways to automate this process, Phing being one of them. The goal of this talk is to really discover what Phing has to offer, from implementing code logic to creating your own task.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
535
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
7
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Build that Phing! PHing Is Not GNU make /Rick Kuipers @rskuipers io@rskuipers.com
  • 2. whoami Rick Kuipers @rskuipers Apeldoorn The Webmen Magento Zend Framework
  • 3. >< A build tool developed for and in PHP Installation through PEAR or Composer $ pear channel-discover pear.phing.info $ pear install --alldeps phing/phing
  • 4. >< vs PHP PEAR build.xml Java apt-get build.xml
  • 5. Skeleton Application
  • 6. build.xml
  • 7. <?xml version="1.0"?> <project name="zf2" default="build"> <target name="build" /> </project>
  • 8. $ phing -l Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies Default target: ------------------------------------------------------------------------------- build Subtargets: ------------------------------------------------------------------------------- build
  • 9. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 tutorial > build: BUILD FINISHED Total time: 0.0457 seconds
  • 10. Fundamentals Properties FileSets PatternSets Tasks
  • 11. Properties <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" />
  • 12. FileSets <fileset id="php.files" dir="."> <include name="*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  • 13. <fileset id="php.files" dir="."> <include name="*/*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  • 14. <fileset id="php.files" dir="."> <include name="**/*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  • 15. PatternSets <patternset id="php.patternset"> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </patternset> <fileset id="php.files" dir="${src.dir}"> <patternset refid="php.patternset" /> </fileset>
  • 16. Let's put it together! <?xml version="1.0"?> <project name="zf2" default="build"> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" /> </project>
  • 17. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 > build: BUILD FINISHED Total time: 0.0492 seconds
  • 18. How do we use Phing QA during module development Combination with CI
  • 19. Quality Assurance "Quality Assurance (QA) is a way of preventing mistakes or defects in manufactured products and avoiding problems when delivering solutions or services to customers."
  • 20. QA Tools PHP Lint PHP Mess Detector PHP Code Sniffer PHP Unit
  • 21. Example 1. <?php 2. 3. namespace MyModule 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  • 22. PHP Lint Built into the PHP executable. Checks for syntax errors. $ php -l example.php PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting (T_NS_SEPARATOR) o r ';' or '{' in example.php on line 5 Errors parsing example.php
  • 23. Example 1. <?php 2. 3. namespace MyModule 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  • 24. PHP Mess Detector Installation through Git, Composer or as a PEAR package. Detects code smells such as: Possible bugs Suboptimal code Overcomplicated expressions Unused parameters, methods, properties $ phpmd example.php text cleancode,codesize,controversial,design,naming,unusedcode example.php:7 Avoid variables with short names like $x. Configured minimum length is 3. example.php:7 Avoid variables with short names like $y. Configured minimum length is 3. example.php:7 Avoid variables with short names like $z. Configured minimum length is 3. example.php:7 Avoid unused parameters such as '$z'.
  • 25. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  • 26. PHP Code Sniffer Installation through Git, Composer or as a PEAR package. Checks your code for coding standards such as: PEAR PSR1 PSR2 Zend Squiz $ phpcs --standard=PSR2 example.php -------------------------------------------------------------------------------- FOUND 4 ERROR(S) AFFECTING 4 LINE(S) -------------------------------------------------------------------------------- 5 | ERROR | Opening brace of a class must be on the line after the definition 7 | ERROR | Visibility must be declared on method "sum" 12 | ERROR | The closing brace for the class must go on the next line after | | the body 13 | ERROR | A closing tag is not permitted at the end of a PHP file --------------------------------------------------------------------------------
  • 27. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  • 28. PHP Unit Installation through PHAR, Composer or as a PEAR package. Runs tests on your code. Provides a framework to create tests. <?php namespace MyModule; require_once('example.php'); class ExampleTest extends PHPUnit_Framework_TestCase { public function testSum() { $example = new Example(); $this->assertEquals($example->sum(2, 3, 5), 10); } }
  • 29. PHP Unit $ phpunit . PHPUnit 3.7.29 by Sebastian Bergmann. F Time: 17 ms, Memory: 2.75Mb There was 1 failure: 1) MyModuleExampleTest::testSum Failed asserting that 5 matches expected 10. /var/www/talk-phing/web/examples/qa-basics/tests/ExampleTest.php:13 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
  • 30. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  • 31. Tasks Core Tasks AdhocTaskdefTask AdhocTypedefTask AppendTask ApplyTask AvailableTask ChmodTask ChownTask ConditionTask CopyTask CvsTask CvsPassTask DeleteTask EchoTask ExecTask FailTask ForeachTask IfTask ImportTask IncludePathTask InputTask LoadFileTask MkdirTask MoveTask PhingTask PhingCallTask PhpEvalTask PropertyTask PropertyPromptTask ReflexiveTask ResolvePathTask TaskdefTask TouchTask TryCatchTask TstampTask TypedefTask UpToDateTask WaitForTask XsltTask
  • 32. Optional Tasks ApiGenTask CoverageMergerTask CoverageReportTask CoverageSetupTask CoverageThresholdTask DbDeployTask DocBloxTask ExportPropertiesTask FileHashTask FileSizeTask FileSyncTask FtpDeployTask GitInitTask GitCloneTask GitGcTask GitBranchTask GitFetchTask GitCheckoutTask GitCommitTask GitMergeTask GitPullTask GitPushTask GitTagTask GitLogTask GrowlNotifyTask HttpGetTask HttpRequestTask IoncubeEncoderTask IoncubeLicenseTask JslLintTask JsMinTask LiquibaseChangeLogTask LiquibaseDbDocTask LiquibaseDiffTask LiquibaseRollbackTask LiquibaseTagTask LiquibaseUpdateTask MailTask ParallelTask PatchTask
  • 33. PDOSQLExecTask PearPackageTask PearPackage2Task PharPackageTask PhkPackageTask PhpCodeSnifferTask PHPCPDTask PHPLocTask PHPMDTask PhpDependTask PhpDocumentorTask DocBloxTask PhpDocumentorExternalTask PhpLintTask PHPUnitTask PHPUnitReport rSTTask S3PutTask S3GetTask ScpTask SshTask SimpleTestTask SvnCheckoutTask SvnCommitTask SvnCopyTask SvnExportTask SvnInfoTask SvnLastRevisionTask SvnListTask SvnLogTask SvnUpdateTask SvnSwitchTask SymfonyConsoleTask SymlinkTask TarTask UntarTask UnzipTask VersionTask WikiPublishTask XmlLintTask
  • 34. XmlPropertyTask ZendCodeAnalyzerTask ZendGuardEncodeTask ZendGuardLicenseTask ZipTask
  • 35. Automating QA
  • 36. PHPLint Task <target name="phplint"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target>
  • 37. PHPCodeSniffer Task <target name="phpcs"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target>
  • 38. PHPMD Task <target name="phpmd"> <phpmd> <fileset refid="php.files" /> </phpmd> </target>
  • 39. PHPUnit Task <target name="phpunit"> <exec command="phpunit -c ${src.dir}/Application/test/" passthru="true" checkreturn="true" /> <exec command="phpunit -c ${src.dir}/Album/test/" passthru="true" checkreturn="true" /> </target>
  • 40. <?xml version="1.0"?> <project name="zf2" default="build"> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" /> <target name="phplint"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target> <target name="phpmd"> <phpmd> <fileset refid="php.files" /> </phpmd> </target> <target name="phpunit"> <exec command="phpunit -c ${src.dir}/Application/test/" passthru="true" checkreturn="true" /> <exec command="phpunit -c ${src.dir}/Album/test/" passthru="true" checkreturn="true" /> </target> </project>
  • 41. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 > build: BUILD FINISHED Total time: 0.0540 seconds
  • 42. Dependencies <target name="build" depends="phplint, phpcs, phpmd, phpunit" />
  • 43. $ phing Buildfile: /var/www/zf2/build.xml zf2 > phplint: BUILD FAILED exception 'IOException' with message 'Unable to open /var/www/zf2/build/cache/lint.cache for writing: ' in /usr/share/php/phing/system/io/FileOutputStream.php:59 Stack trace: #0 /usr/share/php/phing/system/io/FileWriter.php(38): FileOutputStream->__construct(Object(Ph ingFile), false) #1 /usr/share/php/phing/util/DataStore.php(146): FileWriter->__construct(Object(PhingFile)) #2 /usr/share/php/phing/util/DataStore.php(107): DataStore->write() #3 /usr/share/php/phing/tasks/ext/PhpLintTask.php(198): DataStore->commit() #4 /usr/share/php/phing/UnknownElement.php(96): PhpLintTask->main() #5 /usr/share/php/phing/Task.php(260): UnknownElement->main() #6 /usr/share/php/phing/Target.php(297): Task->perform() #7 /usr/share/php/phing/Target.php(320): Target->main() #8 /usr/share/php/phing/Project.php(824): Target->performTasks() #9 /usr/share/php/phing/Project.php(797): Project->executeTarget('build') #10 /usr/share/php/phing/Phing.php(586): Project->executeTargets(Array) #11 /usr/share/php/phing/Phing.php(170): Phing->runBuild() #12 /usr/share/php/phing/Phing.php(278): Phing::start(Array, NULL) #13 /usr/share/php/phing.php(43): Phing::fire(Array) #14 {main} Total time: 0.1397 seconds
  • 44. <target name="prepare"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target>
  • 45. <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target> © Stephan Hochdörfer
  • 46. <target name="phplint" depends="-prepare"> <!-- ... --> </target> <target name="phpcs" depends="-prepare"> <!-- ... --> </target> <target name="phpmd" depends="-prepare"> <!-- ... --> </target> <target name="phpunit" depends="-prepare"> <!-- ... --> </target>
  • 47. $ phing Buildfile: /var/www/zf2/build.xml zf2 > -prepare: zf2 > phplint: zf2 > phpcs: FILE: /var/www/zf2/module/Application/view/layout/layout.phtml -------------------------------------------------------------------------------- FOUND 0 ERROR(S) AND 5 WARNING(S) AFFECTING 5 LINE(S) -------------------------------------------------------------------------------- 6 | WARNING | Line exceeds 120 characters; contains 127 characters 11 | WARNING | Line exceeds 120 characters; contains 154 characters 17 | WARNING | Line exceeds 120 characters; contains 137 characters 33 | WARNING | Line exceeds 120 characters; contains 125 characters 36 | WARNING | Line exceeds 120 characters; contains 123 characters --------------------------------------------------------------------------------
  • 48. zf2 > phpmd: [phpmd] Processing files... /var/www/zf2/module/Album/src/Album/Form/AlbumForm.php:8 Avoid unused parameters such as '$ name'. /var/www/zf2/module/Album/src/Album/Model/Album.php:33 Avoid unused parameters such as '$ inputFilter'. [phpmd] Finished processing files zf2 > phpunit: PHPUnit 4.0.14 by Sebastian Bergmann. Configuration read from /var/www/zf2/module/Application/test/phpunit.xml.dist . Time: 42 ms, Memory: 5.75Mb OK (1 test, 1 assertion) PHPUnit 4.0.14 by Sebastian Bergmann. Configuration read from /var/www/zf2/module/Album/test/phpunit.xml.dist ............. Time: 72 ms, Memory: 8.50Mb OK (13 tests, 22 assertions) zf2 > build: BUILD FINISHED
  • 49. Logical tasks IfTask ConditionTask FailTask ForeachTask
  • 50. IfTask <property name="foo" value="bar" /> <if> <equals arg1="${foo}" arg2="bar" /> <then> <echo message="The value of property foo is bar" /> </then> <else> <echo message="The value of property foo is not bar" /> </else> </if>
  • 51. ConditionTask <condition property="IsPhingRecursiveAcronym"> <contains string="PHing Is Not GNU make" substring="phing" casesensitive="false" /> </condition> <if> <istrue value="${IsPhingRecursiveAcronym}" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's recursive! BUILD FINISHED Total time: 0.0487 seconds
  • 52. <condition property="IsXmlRecursiveAcronym"> <contains string="Extensible Markup Language" substring="XML" casesensitive="false" /> </condition> <if> <istrue value="${IsXmlRecursiveAcronym}" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's recursive! BUILD FINISHED Total time: 0.0524 seconds
  • 53. <condition property="IsXmlRecursiveAcronym"> <contains string="Extensible Markup Language" substring="XML" casesensitive="false" /> </condition> <if> <isset property="IsXmlRecursiveAcronym" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's not recursive! BUILD FINISHED Total time: 0.0468 seconds
  • 54. FailTask <fail message="Failed for some reason!" /> <fail if="errorprop" message="Detected error!" /> <fail unless="dontfail" message="Detected error!" />
  • 55. ForeachTask <fileset id="fruits" dir="."> <include name="fruits/*.xml" /> <include name="**/*.php" /> </fileset> <target name="build"> <foreach param="fruit" target="displayfruit"> <fileset refid="fruits" /> </foreach> <foreach list="apple;orange;pear;banana" target="displayfruit" param="fruit" delimiter=";" /> </target> <target name="displayfruit"> <echo message="${fruit}" /> </target>
  • 56. Interesting Tasks PropertyPromptTask PhpEvalTask
  • 57. PropertyPromptTask <?xml version="1.0" encoding="UTF-8"?> <project name="Example" default="build"> <propertyprompt propertyName="messages.name" promptText="Please enter your name" defaultValue="anonymous" /> <property name="messages.welcome" value="Hello, ${messages.name}!" /> <target name="build" description="Displays the project name and a personalized welcome message" <echo message="${phing.project.name}: ${messages.welcome}" /> </target> </project>
  • 58. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-prompt/build.xml Please enter your name [anonymous] ? Rick Example > build: [echo] Example: Hello, Rick! BUILD FINISHED Total time: 3.7389 seconds
  • 59. PhpEvalTask <?xml version="1.0" encoding="UTF-8"?> <project name="Example" default="build"> <target name="build"> <php expression="function increment($i) { return ++$i; }" /> <php function="increment" returnProperty="result"> <param>1</param> </php> <echo message="${result}" /> </target> </project>
  • 60. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-php-eval/build.xml Example > build: [php] Evaluating PHP expression: function increment($i) { return ++$i; } [php] Calling PHP function: increment() [echo] 2 BUILD FINISHED Total time: 0.0511 seconds
  • 61. <?xml version="1.0"?> <project name="Testing Framework" default="build"> <property name="haltOnFail" value="true" /> <target name="build"> <php function="ucfirst" returnProperty="result"> <param>phing</param> </php> <property name="expected" value="Phing" override="true" /> <phingcall target="test" /> <php expression="preg_replace('/php/', 'xml', 'PHP')" returnProperty="result" /> <property name="expected" value="xml" override="true" /> <phingcall target="test" /> </target> <target name="test"> <if> <equals arg1="${result}" arg2="${expected}" casesensitive="true" /> <then> <echo>✔</echo> </then> <else> <echo>✘</echo> <fail if="haltOnFail"> Expected: ${expected} Result: ${result} </fail> </else> </if> </target> </project>
  • 62. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-testing-framework/build.xml Testing Framework > build: [php] Calling PHP function: ucfirst() [phingcall] Calling Buildfile '/var/www/talk-phing/web/examples/phing-testing-framework/build .xml' with target 'test' Testing Framework > test: [echo] ✔ [php] Evaluating PHP expression: preg_replace('/php/', 'xml', 'PHP') [phingcall] Calling Buildfile '/var/www/talk-phing/web/examples/phing-testing-framework/build .xml' with target 'test' Testing Framework > test: [echo] ✘ [if] Error in IfTask Execution of target "test" failed for the following reason: /var/www/talk-phing/web/examples/ phing-testing-framework/build.xml:19:12: Error in IfTask Previous exception 'BuildException' with message '/var/www/talk-phing/web/examples/phing-test ing-framework/build.xml:26:25: /var/www/talk-phing/web/examples/phing-testing-framework/build .xml:26:25: Expected: xml Result: PHP
  • 63. Extending our phpunit target <target name="phpunit" depends="-prepare"> <propertyprompt defaultValue="all" promptText="Which module would you like to run the tests for?" propertyName="module" /> <if> <equals arg1="${module}" arg2="all" /> <then> <phingcall target="-run-all-tests" /> </then> <else> <property name="absFile" value="${src.dir}/${module}/test/phpunit.xml.dist" /> <phingcall target="-run-test" /> </else> </if> </target> <target name="-run-all-tests" hidden="true"> <foreach param="file" absparam="absFile" target="-run-test"> <fileset dir="${src.dir}"> <include name="*/test/phpunit.xml*" /> </fileset> </foreach> </target> <target name="-run-test" hidden="true"> <php function="dirname" returnProperty="phpunitConfigDir"> <param>${absFile}</param> </php> <exec command="phpunit -c ${phpunitConfigDir}" passthru="true" checkreturn="true" /> </target>
  • 64. Create your own Task
  • 65. VDD var_dump driven development XDebug or PHPDBG
  • 66. VarDumpTask Accept a fileset Find lines that contain var_dump Ignore comments Show the files and line numbers that match Halt on match
  • 67. <?php require_once 'phing/Task.php'; class VarDumpTask extends Task { public function main() { } }
  • 68. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { protected $_fileSets = array(); public function main() { } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet()); return $this->_fileSets[$num-1]; } }
  • 69. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { protected $_fileSets = array(); public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet()); return $this->_fileSets[$num-1]; } }
  • 70. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { const VAR_DUMP = 'var_dump('; protected $_fileSets = array(); public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } $project = $this->getProject(); foreach ($this->_fileSets as $fs) { $files = $fs->getDirectoryScanner($project)->getIncludedFiles(); $dir = $fs->getDir($this->project)->getPath(); foreach($files as &$file) { $fullfile = $dir . DIRECTORY_SEPARATOR . $file; if (($nr = $this->_grep($fullfile, self::VAR_DUMP, '//'))) { $this->log($fullfile . ':' . $nr); } } } } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet());
  • 71. protected function _grep($file, $val, $ignoreLinesWith = null) { $lines = file($file); foreach ($lines as $nr => $line) { if (strpos($line, $val) !== false) { if (!isset($ignoreLinesWith) || strpos($line, $ignoreLinesWith) === false) { return $nr; } } } return false; }
  • 72. protected $_haltOnMatch = false; public function setHaltOnMatch($haltOnMatch = null) { if (isset($haltOnMatch)) { $this->_haltOnMatch = true; } }
  • 73. public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } $project = $this->getProject(); $found = false; foreach ($this->_fileSets as $fs) { $files = $fs->getDirectoryScanner($project)->getIncludedFiles(); $dir = $fs->getDir($project)->getPath(); foreach($files as &$file) { $fullfile = $dir . DIRECTORY_SEPARATOR . $file; if (($nr = $this->_grep($fullfile, self::VAR_DUMP, '//'))) { $this->log($fullfile . ':' . $nr); $found = true; } } } if ($found && $this->_haltOnMatch) { throw new BuildException('Found traces of var_dump in filesets'); } }
  • 74. Defining your task AdhocTaskdefTask TaskdefTask
  • 75. AdhocTaskdefTask <adhoc-task name="foo"> <![CDATA[ class FooTest extends Task { private $bar; function setBar($bar) { $this->bar = $bar; } function main() { $this->log("In FooTest: " . $this->bar); } } ]]> </adhoc-task>
  • 76. TaskdefTask <taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
  • 77. Using our VarDumpTask <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <target name="vdd" depends="-prepare"> <vdd haltOnMatch="true"> <fileset refid="php.files" /> </vdd> </target>
  • 78. $ phing vdd Buildfile: /var/www/zf2/build.xml zf2 > -prepare: zf2 > vdd: [vdd] /var/www/zf2/module/Album/Module.php:15 Execution of target "vdd" failed for the following reason: /var/www/zf2/build.xml:48:25: Foun d traces of var_dump in filesets BUILD FAILED /var/www/zf2/build.xml:48:25: Found traces of var_dump in filesets Total time: 0.0687 seconds
  • 79. <?xml version="1.0"?> <project name="zf2" default="build"> <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" depends="phplint, phpcs, phpmd, phpunit, vdd" /> <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target>
  • 80. <target name="phplint" depends="-prepare"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs" depends="-prepare"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target> <target name="phpmd" depends="-prepare"> <phpmd> <fileset refid="php.files" /> </phpmd> </target> <target name="vdd" depends="-prepare"> <vdd haltOnMatch="true"> <fileset refid="php.files" /> </vdd> </target>
  • 81. <target name="phpunit" depends="-prepare"> <propertyprompt defaultValue="all" promptText="Which module would you like to run the tests for? propertyName="module" /> <if> <equals arg1="${module}" arg2="all" /> <then> <phingcall target="-run-all-tests" /> </then> <else> <property name="absFile" value="${src.dir}/${module}/test/phpunit.xml.dist" /> <phingcall target="-run-test" /> </else> </if> </target> <target name="-run-all-tests" hidden="true"> <foreach param="file" absparam="absFile" target="-run-test"> <fileset dir="${src.dir}"> <include name="*/test/phpunit.xml*" /> </fileset> </foreach> </target> <target name="-run-test" hidden="true"> <php function="dirname" returnProperty="phpunitConfigDir"> <param>${absFile}</param> </php> <exec command="phpunit -c ${phpunitConfigDir}" passthru="true" checkreturn="true" /> </target> </project>
  • 82. Duplicate build file logic Build file inheritance Git submodules
  • 83. phing/default.xml <?xml version="1.0"?> <project name="zf2"> <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target> <target name="phplint" depends="-prepare"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs" depends="-prepare"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" />
  • 84. build.xml <?xml version="1.0"?> <project name="zf2" default="build"> <import file="phing/default.xml" /> <target name="build" depends="phplint, phpcs, phpmd, phpunit, vdd" /> </project>
  • 85. Documentation http://www.phing.info/docs/guide/stable/ https://github.com/phingofficial/phing