Download - Build That Phing!

Transcript
Page 1: Build That Phing!

Build that Phing!PHing Is Not GNU make

/ Rick Kuipers @[email protected]

Page 2: Build That Phing!

whoamiRick Kuipers@rskuipersApeldoornThe WebmenMagentoZend Framework

Page 3: Build That Phing!

><A build tool developed for and in PHPInstallation through PEAR or Composer$ pear channel-discover pear.phing.info$ pear install --alldeps phing/phing

Page 4: Build That Phing!

>< vs PHPPEAR

build.xml

Javaapt-get

build.xml

Page 5: Build That Phing!

Skeleton Application

Page 6: Build That Phing!
Page 7: Build That Phing!

build.xml

Page 8: Build That Phing!

<?xml version="1.0"?><project name="zf2" default="build">

<target name="build" />

</project>

Page 9: Build That Phing!

$ phing -lBuildfile: /var/www/zf2/build.xmlWarning: target 'build' has no tasks or dependenciesDefault target:------------------------------------------------------------------------------- build

Subtargets:------------------------------------------------------------------------------- build

Page 10: Build That Phing!

$ phingBuildfile: /var/www/zf2/build.xmlWarning: target 'build' has no tasks or dependencies

zf2 tutorial > build:

BUILD FINISHED

Total time: 0.0457 seconds

Page 11: Build That Phing!

FundamentalsProperties

FileSetsPatternSets

Tasks

Page 12: Build That Phing!

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" />

Page 13: Build That Phing!

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

Page 14: Build That Phing!

<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

Page 15: Build That Phing!

<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

Page 16: Build That Phing!

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>

Page 17: Build That Phing!

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>

Page 18: Build That Phing!

$ phingBuildfile: /var/www/zf2/build.xmlWarning: target 'build' has no tasks or dependencies

zf2 > build:

BUILD FINISHED

Total time: 0.0492 seconds

Page 19: Build That Phing!

How do we use PhingQA during module development

Combination with CI

Page 20: Build That Phing!

Quality Assurance"Quality Assurance (QA) is a way of preventing

mistakes or defects in manufactured products andavoiding problems when delivering solutions or

services to customers."

Page 21: Build That Phing!

QA ToolsPHP LintPHP Mess DetectorPHP Code SnifferPHP Unit

Page 22: Build That Phing!

Example 1. <?php 2. 3. namespace My\Module 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y;10. }11.12. }13. ?>

Page 23: Build That Phing!

PHP LintBuilt 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) or ';' or '{' in example.php on line 5Errors parsing example.php

Page 24: Build That Phing!

Example 1. <?php 2. 3. namespace My\Module 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y;10. }11.12. }13. ?>

Page 25: Build That Phing!

PHP Mess DetectorInstallation through Git, Composer or as a PEAR package.Detects code smells such as:

Possible bugsSuboptimal codeOvercomplicated expressionsUnused 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'.

Page 26: Build That Phing!

Example 1. <?php 2. 3. namespace My\Module; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y;10. }11.12. }13. ?>

Page 27: Build That Phing!

PHP Code SnifferInstallation through Git, Composer or as a PEAR package.Checks your code for coding standards such as:

PEARPSR1PSR2ZendSquiz

$ 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--------------------------------------------------------------------------------

Page 28: Build That Phing!

Example 1. <?php 2. 3. namespace My\Module; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y;10. }11.12. }13. ?>

Page 29: Build That Phing!

PHP UnitInstallation through PHAR, Composer or as a PEAR package.Runs tests on your code.Provides a framework to create tests.

<?php

namespace My\Module;

require_once('example.php');

class ExampleTest extends \PHPUnit_Framework_TestCase{

public function testSum() { $example = new Example(); $this->assertEquals($example->sum(2, 3, 5), 10); }}

Page 30: Build That Phing!

PHP Unit$ phpunit .

PHPUnit 3.7.29 by Sebastian Bergmann.

F

Time: 17 ms, Memory: 2.75Mb

There was 1 failure:

1) My\Module\ExampleTest::testSumFailed 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.

Page 31: Build That Phing!

Example 1. <?php 2. 3. namespace My\Module; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y;10. }11.12. }13. ?>

Page 32: Build That Phing!

TasksCore Tasks

AdhocTaskdefTaskAdhocTypedefTaskAppendTaskApplyTaskAvailableTaskChmodTaskChownTaskConditionTaskCopyTaskCvsTaskCvsPassTaskDeleteTaskEchoTask

ExecTaskFailTaskForeachTaskIfTaskImportTaskIncludePathTaskInputTaskLoadFileTaskMkdirTaskMoveTaskPhingTaskPhingCallTaskPhpEvalTask

PropertyTaskPropertyPromptTaskReflexiveTaskResolvePathTaskTaskdefTaskTouchTaskTryCatchTaskTstampTaskTypedefTaskUpToDateTaskWaitForTaskXsltTask

Page 33: Build That Phing!

Optional TasksApiGenTaskCoverageMergerTaskCoverageReportTaskCoverageSetupTaskCoverageThresholdTaskDbDeployTaskDocBloxTaskExportPropertiesTaskFileHashTaskFileSizeTaskFileSyncTaskFtpDeployTaskGitInitTaskGitCloneTaskGitGcTaskGitBranchTaskGitFetchTaskGitCheckoutTaskGitCommitTaskGitMergeTask

GitPullTaskGitPushTaskGitTagTaskGitLogTaskGrowlNotifyTaskHttpGetTaskHttpRequestTaskIoncubeEncoderTaskIoncubeLicenseTaskJslLintTaskJsMinTaskLiquibaseChangeLogTaskLiquibaseDbDocTaskLiquibaseDiffTaskLiquibaseRollbackTaskLiquibaseTagTaskLiquibaseUpdateTaskMailTaskParallelTaskPatchTask

Page 34: Build That Phing!

PDOSQLExecTaskPearPackageTaskPearPackage2TaskPharPackageTaskPhkPackageTaskPhpCodeSnifferTaskPHPCPDTaskPHPLocTaskPHPMDTaskPhpDependTaskPhpDocumentorTaskDocBloxTaskPhpDocumentorExternalTaskPhpLintTaskPHPUnitTaskPHPUnitReportrSTTaskS3PutTaskS3GetTaskScpTask

SshTaskSimpleTestTaskSvnCheckoutTaskSvnCommitTaskSvnCopyTaskSvnExportTaskSvnInfoTaskSvnLastRevisionTaskSvnListTaskSvnLogTaskSvnUpdateTaskSvnSwitchTaskSymfonyConsoleTaskSymlinkTaskTarTaskUntarTaskUnzipTaskVersionTaskWikiPublishTaskXmlLintTask

Page 35: Build That Phing!

XmlPropertyTaskZendCodeAnalyzerTaskZendGuardEncodeTaskZendGuardLicenseTaskZipTask

Page 36: Build That Phing!

Automating QA

Page 37: Build That Phing!

PHPLint Task<target name="phplint"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint></target>

Page 38: Build That Phing!

PHPCodeSniffer Task<target name="phpcs"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer></target>

Page 39: Build That Phing!

PHPMD Task<target name="phpmd"> <phpmd> <fileset refid="php.files" /> </phpmd></target>

Page 40: Build That Phing!

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>

Page 41: Build That Phing!

<?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>

Page 42: Build That Phing!

$ phingBuildfile: /var/www/zf2/build.xmlWarning: target 'build' has no tasks or dependencies

zf2 > build:

BUILD FINISHED

Total time: 0.0540 seconds

Page 43: Build That Phing!

Dependencies<target name="build" depends="phplint, phpcs, phpmd, phpunit" />

Page 44: Build That Phing!

$ phingBuildfile: /var/www/zf2/build.xml

zf2 > phplint:

BUILD FAILEDexception 'IOException' with message 'Unable to open /var/www/zf2/build/cache/lint.cache for writing: ' in /usr/share/php/phing/system/io/FileOutputStream.php:59Stack trace:#0 /usr/share/php/phing/system/io/FileWriter.php(38): FileOutputStream->__construct(Object(PhingFile), 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

Page 45: Build That Phing!

<target name="prepare"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /></target>

Page 46: Build That Phing!

<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

Page 47: Build That Phing!

<target name="phplint" depends="-prepare"> <!-- ... --></target>

<target name="phpcs" depends="-prepare"> <!-- ... --></target>

<target name="phpmd" depends="-prepare"> <!-- ... --></target>

<target name="phpunit" depends="-prepare"> <!-- ... --></target>

Page 48: Build That Phing!

$ phingBuildfile: /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--------------------------------------------------------------------------------

Page 49: Build That Phing!

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

Page 50: Build That Phing!

Logical tasksIfTask

ConditionTaskFailTask

ForeachTask

Page 51: Build That Phing!

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>

Page 52: Build That Phing!

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>

$ phingBuildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml

Example > build:

[echo] It's recursive!

BUILD FINISHED

Total time: 0.0487 seconds

Page 53: Build That Phing!

<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>

$ phingBuildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml

Example > build:

[echo] It's recursive!

BUILD FINISHED

Total time: 0.0524 seconds

Page 54: Build That Phing!

<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>

$ phingBuildfile: /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

Page 55: Build That Phing!

FailTask<fail message="Failed for some reason!" />

<fail if="errorprop" message="Detected error!" />

<fail unless="dontfail" message="Detected error!" />

Page 56: Build That Phing!

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>

Page 57: Build That Phing!

Interesting TasksPropertyPromptTask

PhpEvalTask

Page 58: Build That Phing!

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>

Page 59: Build That Phing!

$ phingBuildfile: /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

Page 60: Build That Phing!

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>

Page 61: Build That Phing!

$ phingBuildfile: /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

Page 62: Build That Phing!

<?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>

Page 63: Build That Phing!

$ phingBuildfile: /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 IfTaskExecution of target "test" failed for the following reason: /var/www/talk-phing/web/examples/phing-testing-framework/build.xml:19:12: Error in IfTaskPrevious exception 'BuildException' with message '/var/www/talk-phing/web/examples/phing-testing-framework/build.xml:26:25: /var/www/talk-phing/web/examples/phing-testing-framework/build.xml:26:25:Expected: xmlResult: PHP

Page 64: Build That Phing!

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>

Page 65: Build That Phing!

Create your own Task

Page 66: Build That Phing!

VDDvar_dump driven development

XDebug or PHPDBG

Page 67: Build That Phing!

VarDumpTaskAccept a filesetFind lines that contain var_dumpIgnore commentsShow the files and line numbers that matchHalt on match

Page 68: Build That Phing!

<?php

require_once 'phing/Task.php';

class VarDumpTask extends Task{

public function main() {

}}

Page 69: Build That Phing!

<?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]; }}

Page 70: Build That Phing!

<?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]; }}

Page 71: Build That Phing!

<?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());

Page 72: Build That Phing!

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; }

Page 73: Build That Phing!

protected $_haltOnMatch = false;

public function setHaltOnMatch($haltOnMatch = null) { if (isset($haltOnMatch)) { $this->_haltOnMatch = true; } }

Page 74: Build That Phing!

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'); } }

Page 75: Build That Phing!

Defining your taskAdhocTaskdefTask

TaskdefTask

Page 76: Build That Phing!

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>

Page 77: Build That Phing!

TaskdefTask<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />

Page 78: Build That Phing!

Using our VarDumpTask<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />

<target name="vdd" depends="-prepare"> <vdd haltOnMatch="true"> <fileset refid="php.files" /> </vdd></target>

Page 79: Build That Phing!

$ phing vddBuildfile: /var/www/zf2/build.xml

zf2 > -prepare:

zf2 > vdd:

[vdd] /var/www/zf2/module/Album/Module.php:15Execution of target "vdd" failed for the following reason: /var/www/zf2/build.xml:48:25: Found traces of var_dump in filesets

BUILD FAILED/var/www/zf2/build.xml:48:25: Found traces of var_dump in filesetsTotal time: 0.0687 seconds

Page 80: Build That Phing!

<?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>

Page 81: Build That Phing!

<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>

Page 82: Build That Phing!

<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>

Page 83: Build That Phing!

Duplicate build file logicBuild file inheritance

Git submodules

Page 84: Build That Phing!

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" />

Page 85: Build That Phing!

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>

Page 86: Build That Phing!

Documentationhttp://www.phing.info/docs/guide/stable/https://github.com/phingofficial/phing