#!/usr/bin/env php getMessage(); echo 'Cannot initialize Phar'; exit(1); } __HALT_COMPILER(); ?>  phing.phara:4:{s:7:"version";s:6:"2.16.0";s:5:"state";s:6:"stable";s:9:"builddate";s:8:"20161222";s:7:"authors";a:1:{s:12:"Michiel Rook";a:1:{s:6:"e-mail";s:13:"mrook@php.net";}}}classes/phing/TaskContainer.php5\X7F.$classes/phing/tasks/ext/SassTask.php{5\X{f-classes/phing/tasks/ext/apigen/ApiGenTask.php+5\X+QҶ-classes/phing/tasks/ext/creole/CreoleTask.phpH5\XHֶ4classes/phing/tasks/ext/creole/CreoleSQLExecTask.phpRJ5\XRJ$+-classes/phing/tasks/ext/git/GitCommitTask.phpa5\Xa*classes/phing/tasks/ext/git/GitTagTask.php)5\X) ,classes/phing/tasks/ext/git/GitFetchTask.php5\XI0/classes/phing/tasks/ext/git/GitCheckoutTask.php5\X)classes/phing/tasks/ext/git/GitGcTask.phpm5\XmX+-classes/phing/tasks/ext/git/GitBranchTask.php 5\X ΂9,classes/phing/tasks/ext/git/GitMergeTask.php5\Xֶ/classes/phing/tasks/ext/git/GitDescribeTask.php5\X&+classes/phing/tasks/ext/git/GitPushTask.php5\X;+classes/phing/tasks/ext/git/GitBaseTask.php5\X9+classes/phing/tasks/ext/git/GitInitTask.php 5\X jbq,classes/phing/tasks/ext/git/GitCloneTask.php5\X9+classes/phing/tasks/ext/git/GitPullTask.php-'5\X-'b"*classes/phing/tasks/ext/git/GitLogTask.php5\X_ބAclasses/phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php 5\X }V5classes/phing/tasks/ext/phpdoc/PhpDocumentor2Task.phpH5\XHhY\~8classes/phing/tasks/ext/phpdoc/PhpDocumentor2Wrapper.phpI5\XI<0:classes/phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php"5\X" Ѷ4classes/phing/tasks/ext/phpdoc/PhpDocumentorTask.php55\X5<classes/phing/tasks/ext/phpdoc/PhpDocumentorExternalTask.php5\X|޶1classes/phing/tasks/ext/inifile/IniFileRemove.php%5\X%c/classes/phing/tasks/ext/inifile/IniFileTask.php$5\X$ƛ .classes/phing/tasks/ext/inifile/IniFileSet.php9 5\X9 O>1classes/phing/tasks/ext/inifile/IniFileConfig.php5\X w%classes/phing/tasks/ext/ThrowTask.php5\Xm+classes/phing/tasks/ext/HttpRequestTask.php 5\X %"Z+classes/phing/tasks/ext/WikiPublishTask.php$)5\X$)zꣶ7classes/phing/tasks/ext/Service/Amazon/S3/S3PutTask.php+5\X+Fp7classes/phing/tasks/ext/Service/Amazon/S3/S3GetTask.php 5\X @-classes/phing/tasks/ext/Service/Amazon/S3.php5\X,*classes/phing/tasks/ext/Service/Amazon.phpu 5\Xu V"_%classes/phing/tasks/ext/PatchTask.php+5\X+Զ>classes/phing/tasks/ext/phpcs/Reports_PhingRemoveFromCache.php 5\X PMG<classes/phing/tasks/ext/phpcs/PhpCodeSnifferTask_Wrapper.phpc5\XcN'classes/phing/tasks/ext/JslLintTask.php;+5\X;+0-classes/phing/tasks/ext/PackageAsPathTask.php5\X{0classes/phing/tasks/ext/ZendCodeAnalyzerTask.php 5\X /classes/phing/tasks/ext/pearpackage/Fileset.php5\XxzO)classes/phing/tasks/ext/hg/HgInitTask.php5\X4)classes/phing/tasks/ext/hg/HgPullTask.phpL5\XL)classes/phing/tasks/ext/hg/HgBaseTask.php(5\X(>S(classes/phing/tasks/ext/hg/HgLogTask.php5\X!e(classes/phing/tasks/ext/hg/HgAddTask.php5\Xw;v*classes/phing/tasks/ext/hg/HgCloneTask.php% 5\X% i3)classes/phing/tasks/ext/hg/HgPushTask.php 5\X *&+classes/phing/tasks/ext/hg/HgUpdateTask.php^ 5\X^ Oy(classes/phing/tasks/ext/hg/HgTagTask.phpN 5\XN +m+classes/phing/tasks/ext/hg/HgRevertTask.php 5\X sԻ+classes/phing/tasks/ext/hg/HgCommitTask.php 5\X y,classes/phing/tasks/ext/hg/HgArchiveTask.php5\X45Z37classes/phing/tasks/ext/phk/PhkPackageWebAccessPath.php5\Xy됣.classes/phing/tasks/ext/phk/PhkPackageTask.php55\X5ބ3classes/phing/tasks/ext/phk/PhkPackageWebAccess.php5\XrT߶+classes/phing/tasks/ext/GrowlNotifyTask.phpq<5\Xq<c7classes/phing/tasks/ext/phpmd/PHPMDFormatterElement.php5\X6!̴+classes/phing/tasks/ext/phpmd/PHPMDTask.php})5\X})RL>classes/phing/tasks/ext/phpmd/PHPMDRendererRemoveFromCache.php5\X\}j<classes/phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php^ 5\X^ n:classes/phing/tasks/ext/pdepend/PhpDependLoggerElement.php1 5\X1 91classes/phing/tasks/ext/pdepend/PhpDependTask.php<5\X<͙'classes/phing/tasks/ext/CapsuleTask.php<5\X<PP\/classes/phing/tasks/ext/sonar/SonarProperty.php5\X϶+classes/phing/tasks/ext/sonar/SonarTask.phpI15\XI1'Ѷ>classes/phing/tasks/ext/sonar/SonarConfigurationFileParser.php5\X0(classes/phing/tasks/ext/FileSizeTask.php_ 5\X_ O۶7classes/phing/tasks/ext/coverage/CoverageReportTask.php M5\X MhmW6classes/phing/tasks/ext/coverage/CoverageSetupTask.php5\Xݨx:classes/phing/tasks/ext/coverage/CoverageThresholdTask.php:5\X:9Qo7classes/phing/tasks/ext/coverage/CoverageMergerTask.php 5\X ^{܍3classes/phing/tasks/ext/coverage/CoverageMerger.php(5\X(mG>classes/phing/tasks/ext/coverage/CoverageReportTransformer.php85\X89classes/phing/tasks/ext/zendguard/ZendGuardEncodeTask.php<5\X<h:classes/phing/tasks/ext/zendguard/ZendGuardLicenseTask.phpB5\XByAclasses/phing/tasks/ext/zendserverdeploymenttool/zsdtBaseTask.php 5\X Eclasses/phing/tasks/ext/zendserverdeploymenttool/zsdtValidateTask.php5\Xm#dAclasses/phing/tasks/ext/zendserverdeploymenttool/zsdtPackTask.php5\X6D*.classes/phing/tasks/ext/PhpCodeSnifferTask.php]5\X]cn,classes/phing/tasks/ext/PearPackage2Task.phpN+5\XN+`׶'classes/phing/tasks/ext/XmlLintTask.phpu5\Xufض+classes/phing/tasks/ext/jsmin/JsMinTask.php5\X.L/classes/phing/tasks/ext/ssh/Ssh2MethodParam.php\5\X\@- 'classes/phing/tasks/ext/ssh/SshTask.php3 5\X3 0h9classes/phing/tasks/ext/ssh/Ssh2MethodConnectionParam.php 5\X Ÿ'classes/phing/tasks/ext/ssh/ScpTask.phpZ35\XZ3;1+-classes/phing/tasks/ext/phpcpd/PHPCPDTask.php&5\X&=}Eclasses/phing/tasks/ext/phpcpd/formatter/PMDPHPCPDResultFormatter.php5\X*϶Bclasses/phing/tasks/ext/phpcpd/formatter/PHPCPDResultFormatter.phpc5\XcIclasses/phing/tasks/ext/phpcpd/formatter/DefaultPHPCPDResultFormatter.php 5\X `9classes/phing/tasks/ext/phpcpd/PHPCPDFormatterElement.php5\X-'3$classes/phing/tasks/ext/HttpTask.php65\X6rt'classes/phing/tasks/ext/PhpLintTask.phps"5\Xs"o(classes/phing/tasks/ext/FileSyncTask.php1?5\X1?/iEclasses/phing/tasks/ext/simpletest/SimpleTestDebugResultFormatter.php5\XY-Eclasses/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php5\XBAEclasses/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.phpn 5\Xn HE5classes/phing/tasks/ext/simpletest/SimpleTestTask.php5\XGN@Cclasses/phing/tasks/ext/simpletest/SimpleTestXmlResultFormatter.php5\XhP@classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.phpp5\Xp.Aclasses/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php_ 5\X_ tnGclasses/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php5\X9(classes/phing/tasks/ext/ComposerTask.php5\X9 5classes/phing/tasks/ext/phploc/PHPLocXMLFormatter.php35\X3*8-classes/phing/tasks/ext/phploc/PHPLocTask.php&5\X&眶:classes/phing/tasks/ext/phploc/AbstractPHPLocFormatter.php 5\X f9classes/phing/tasks/ext/phploc/PHPLocFormatterElement.php 5\X _+E6classes/phing/tasks/ext/phploc/PHPLocTextFormatter.php5\X&"5classes/phing/tasks/ext/phploc/PHPLocCSVFormatter.php;5\X;R9classes/phing/tasks/ext/phploc/PHPLocFormatterFactory.php 5\X :+4classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMysql.php5\XQPL/classes/phing/tasks/ext/dbdeploy/DbmsSyntax.php5\XW4classes/phing/tasks/ext/dbdeploy/DbmsSyntaxMsSql.php5\XPn5classes/phing/tasks/ext/dbdeploy/DbmsSyntaxOracle.phpd5\XdgB4classes/phing/tasks/ext/dbdeploy/DbmsSyntaxPgSQL.phps5\Xsv6classes/phing/tasks/ext/dbdeploy/DbmsSyntaxFactory.php 5\X =;5classes/phing/tasks/ext/dbdeploy/DbmsSyntaxSQLite.php5\XCc1classes/phing/tasks/ext/dbdeploy/DbDeployTask.php55\X5CUҋ7classes/phing/tasks/ext/pdo/PlainPDOResultFormatter.php 5\X 25classes/phing/tasks/ext/pdo/XMLPDOResultFormatter.php5\Xk=p.classes/phing/tasks/ext/pdo/PDOSQLExecTask.php*K5\X*KM VO7classes/phing/tasks/ext/pdo/DefaultPDOQuerySplitter.phpX5\XX~:classes/phing/tasks/ext/pdo/PDOSQLExecFormatterElement.php!5\X!;5classes/phing/tasks/ext/pdo/PgsqlPDOQuerySplitter.php(5\X( ~5classes/phing/tasks/ext/pdo/DummyPDOQuerySplitter.php 5\X 1ݶ'classes/phing/tasks/ext/pdo/PDOTask.php5\Xq0classes/phing/tasks/ext/pdo/PDOQuerySplitter.php5\X.2classes/phing/tasks/ext/pdo/PDOResultFormatter.php5\XS:=classes/phing/tasks/ext/SymfonyConsole/SymfonyConsoleTask.php5\Xt.classes/phing/tasks/ext/SymfonyConsole/Arg.php 5\X } 9classes/phing/tasks/ext/liquibase/LiquibaseUpdateTask.phpu5\Xu>7classes/phing/tasks/ext/liquibase/LiquibaseDiffTask.php5\X2✍;classes/phing/tasks/ext/liquibase/AbstractLiquibaseTask.php+5\X+麐8classes/phing/tasks/ext/liquibase/LiquibaseDbDocTask.php5\X7<classes/phing/tasks/ext/liquibase/LiquibaseChangeLogTask.php_5\X_c d3classes/phing/tasks/ext/liquibase/LiquibaseTask.php.5\X.2;classes/phing/tasks/ext/liquibase/LiquibaseRollbackTask.php5\X\6classes/phing/tasks/ext/liquibase/LiquibaseTagTask.phph5\Xhw#classes/phing/tasks/ext/rSTTask.php_/5\X_/M6)classes/phing/tasks/ext/StopwatchTask.php5\XUD#classes/phing/tasks/ext/TarTask.php!<5\X!<&classes/phing/tasks/ext/SmartyTask.phpM5\XMޏ*classes/phing/tasks/ext/AutoloaderTask.php 5\X a2&)classes/phing/tasks/ext/FtpDeployTask.phpg:5\Xg:+classes/phing/tasks/ext/XmlPropertyTask.phpd 5\Xd ͓-classes/phing/tasks/ext/ReplaceRegexpTask.php5\X#tk(classes/phing/tasks/ext/ManifestTask.php|#5\X|#k+classes/phing/tasks/ext/PearPackageTask.php95\X9YD(classes/phing/tasks/ext/ParallelTask.php] 5\X] VL'classes/phing/tasks/ext/SymlinkTask.php5\XZ&៶$classes/phing/tasks/ext/MailTask.php5\X#classes/phing/tasks/ext/ZipTask.php*5\X*oV2classes/phing/tasks/ext/ioncube/IoncubeComment.php5\X׶6classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php5\X)co6classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php<5\X<p80classes/phing/tasks/ext/ExportPropertiesTask.phpI5\XIv?classes/phing/tasks/ext/property/AbstractPropertySetterTask.phpt5\Xtxk2classes/phing/tasks/ext/property/PathToFileSet.php5\Xmu .classes/phing/tasks/ext/property/RegexTask.php5\XxPǶ+classes/phing/tasks/ext/svn/SvnCopyTask.php5\X+*classes/phing/tasks/ext/svn/SvnLogTask.phpB 5\XB Svݶ-classes/phing/tasks/ext/svn/SvnSwitchTask.php> 5\X> 0A߶/classes/phing/tasks/ext/svn/SvnCheckoutTask.php5\X o+classes/phing/tasks/ext/svn/SvnInfoTask.php25\X2+!+classes/phing/tasks/ext/svn/SvnListTask.phpd5\Xdf-classes/phing/tasks/ext/svn/SvnCommitTask.php` 5\X` Hb+classes/phing/tasks/ext/svn/SvnBaseTask.php%5\X%%P-classes/phing/tasks/ext/svn/SvnExportTask.php}5\X}x2-classes/phing/tasks/ext/svn/SvnUpdateTask.phpz5\XzbͶ3classes/phing/tasks/ext/svn/SvnLastRevisionTask.phpk 5\Xk %classes/phing/tasks/ext/UnzipTask.php 5\X I[/classes/phing/tasks/ext/phpunit/PHPUnitUtil.php5\Xhm忶5classes/phing/tasks/ext/phpunit/PHPUnitTestRunner.phpN,5\XN,HKclasses/phing/tasks/ext/phpunit/formatter/SummaryPHPUnitResultFormatter.php5\X<Gclasses/phing/tasks/ext/phpunit/formatter/XMLPHPUnitResultFormatter.php5\X~Dclasses/phing/tasks/ext/phpunit/formatter/PHPUnitResultFormatter.php5\XgfJclasses/phing/tasks/ext/phpunit/formatter/Crap4jPHPUnitResultFormatter.phpV 5\XV !ͨzIclasses/phing/tasks/ext/phpunit/formatter/PlainPHPUnitResultFormatter.phpM5\XMOJclasses/phing/tasks/ext/phpunit/formatter/CloverPHPUnitResultFormatter.php^ 5\X^ ̻^-classes/phing/tasks/ext/phpunit/BatchTest.php>5\X>$Ձ/classes/phing/tasks/ext/phpunit/PHPUnitTask.phpGC5\XGCQж5classes/phing/tasks/ext/phpunit/PHPUnitReportTask.php 5\X ^4classes/phing/tasks/ext/phpunit/FormatterElement.phpG5\XGh*classes/phing/tasks/ext/NotifySendTask.php 5\X 2'classes/phing/tasks/ext/VersionTask.php5\XZ+classes/phing/tasks/ext/ExtractBaseTask.php5\XpC4classes/phing/tasks/ext/phar/PharMetadataElement.php?5\X?O-classes/phing/tasks/ext/phar/PharDataTask.php#5\X#^ -classes/phing/tasks/ext/phar/PharMetadata.php5\XrAF0classes/phing/tasks/ext/phar/PharPackageTask.phpQ.5\XQ.T8(classes/phing/tasks/ext/FileHashTask.phpo5\XoP6'classes/phing/tasks/ext/HttpGetTask.php5\X%classes/phing/tasks/ext/UntarTask.php5\X-ζ&classes/phing/tasks/ext/JsHintTask.php5\X!)classes/phing/tasks/system/AttribTask.php5\Xu -'classes/phing/tasks/system/WarnTask.php5\X Ȁ+classes/phing/tasks/system/TryCatchTask.php5\XY%classes/phing/tasks/system/IfTask.php5\X$v(classes/phing/tasks/system/TouchTask.phpG5\XG}4classes/phing/tasks/system/condition/OsCondition.php 5\X 5classes/phing/tasks/system/condition/PhingVersion.php5\Xzw5classes/phing/tasks/system/condition/NotCondition.php5\X2%5classes/phing/tasks/system/condition/XorCondition.php}5\X}R8classes/phing/tasks/system/condition/NestedCondition.php$5\X$/|}0classes/phing/tasks/system/condition/Matches.phpZ 5\XZ G8classes/phing/tasks/system/condition/EqualsCondition.php 5\X X;9classes/phing/tasks/system/condition/IsFalseCondition.php5\X']@classes/phing/tasks/system/condition/VersionCompareCondition.phpw 5\Xw Ÿö3classes/phing/tasks/system/condition/FilesMatch.php5\Xʬ2classes/phing/tasks/system/condition/Condition.php5\X@classes/phing/tasks/system/condition/IsPropertyTrueCondition.php5\X8classes/phing/tasks/system/condition/IsTrueCondition.php5\XP9Aclasses/phing/tasks/system/condition/IsPropertyFalseCondition.php5\X M6classes/phing/tasks/system/condition/ConditionBase.php(5\X(!ߤ8classes/phing/tasks/system/condition/SocketCondition.php5\XoYRAclasses/phing/tasks/system/condition/ReferenceExistsCondition.php5\X IY7classes/phing/tasks/system/condition/IsSetCondition.php5\X؟y2classes/phing/tasks/system/condition/IsFailure.php]5\X]t7classes/phing/tasks/system/condition/IsFileSelected.php 5\X :classes/phing/tasks/system/condition/ContainsCondition.php 5\X tT;p>classes/phing/tasks/system/condition/HasFreeSpaceCondition.php 5\X Zg6classes/phing/tasks/system/condition/HttpCondition.php 5\X Х4classes/phing/tasks/system/condition/OrCondition.php5\X^5classes/phing/tasks/system/condition/AndCondition.php5\X'V*classes/phing/tasks/system/WaitForTask.php5\Xo(classes/phing/tasks/system/ApplyTask.php_\5\X_\)pn,classes/phing/tasks/system/AvailableTask.phpj5\Xjt'classes/phing/tasks/system/TempFile.phpP5\XPj*classes/phing/tasks/system/CvsPassTask.php5\XQ+classes/phing/tasks/system/BlockForTask.phpW 5\XW CӶ.classes/phing/tasks/system/IncludePathTask.php5\X +classes/phing/tasks/system/LoadFileTask.php5\XN.classes/phing/tasks/system/DiagnosticsTask.phpK5\XK(classes/phing/tasks/system/MkdirTask.php 5\X `w*classes/phing/tasks/system/TypedefTask.php`5\X`'classes/phing/tasks/system/ExecTask.php 75\X 7 *classes/phing/listener/HtmlColorLogger.php5\X%)classes/phing/listener/NoBannerLogger.php\ 5\X\ Ile4classes/phing/listener/StreamRequiredBuildLogger.phpM5\XM)$,classes/phing/listener/TimestampedLogger.php%5\X%H"'classes/phing/listener/TargetLogger.phpZ5\XZÅ(classes/phing/listener/ProfileLogger.php5\X3a3*classes/phing/listener/AnsiColorLogger.php5\X*~%classes/phing/listener/MailLogger.php5\XО%classes/phing/listener/JsonLogger.php5\X;'classes/phing/listener/SilentLogger.php95\X9,Ѷ(classes/phing/listener/DefaultLogger.phpY(5\XY(0*classes/phing/listener/defaults.properties5\XA۶(classes/phing/filters/XincludeFilter.php5\Xx/;$classes/phing/filters/TailFilter.php5\XԌ*classes/phing/filters/TranslateGettext.php&5\X&~&classes/phing/filters/ConcatFilter.phpM5\XMz'*classes/phing/filters/BaseFilterReader.php5\XlQ*classes/phing/filters/StripPhpComments.php5\X*classes/phing/filters/ExpandProperties.php`5\X`9/classes/phing/filters/BaseParamFilterReader.phpw 5\Xw F-)classes/phing/filters/ChainableReader.phpF5\XFpY[%classes/phing/filters/SuffixLines.phpx5\XxYM%classes/phing/filters/IconvFilter.phpY5\XY$ݶ%classes/phing/filters/TabToSpaces.php5\XU \,classes/phing/filters/LineContainsRegexp.phpM5\XMe˶$classes/phing/filters/HeadFilter.php5\X~^*classes/phing/filters/PhpArrayMapLines.php5\X|Q&classes/phing/filters/LineContains.php 5\X sT/classes/phing/filters/ReplaceTokensWithFile.php/5\X/!)(1classes/phing/filters/util/IniFileTokenReader.php;5\X;0classes/phing/filters/util/ChainReaderHelper.php5\X@ʶ+classes/phing/filters/StripLineComments.php5\XÙ%classes/phing/filters/PrefixLines.phpG5\XG&2w'classes/phing/filters/EscapeUnicode.php5\Xj)classes/phing/filters/StripLineBreaks.php5\Xi$classes/phing/filters/XsltFilter.php,5\X,xE'classes/phing/filters/ReplaceTokens.php(75\X(71P$classes/phing/filters/TidyFilter.php5\X$classes/phing/filters/SortFilter.php5\XO)classes/phing/filters/StripWhitespace.php 5\X <˶'classes/phing/filters/ReplaceRegexp.php15\X1(classes/phing/TaskAdapter.php 5\X C?Q)classes/phing/input/YesNoInputRequest.php5\X!2classes/phing/input/MultipleChoiceInputRequest.php5\X8N$classes/phing/input/InputRequest.php> 5\X> #3+classes/phing/input/DefaultInputHandler.php 5\X Z4$classes/phing/input/InputHandler.php5\Xh䏶%classes/phing/IntrospectionHelper.php_5\X_(r"classes/phing/SubBuildListener.phpk 5\Xk B7'classes/phing/BuildTimeoutException.php5\Xqm%classes/phing/ExitStatusException.php|5\X|]V classes/phing/util/FileUtils.php895\X89$classes/phing/util/PathTokenizer.php95\X9ՠ*classes/phing/util/regexp/RegexpEngine.php 5\X m1(classes/phing/util/regexp/PregEngine.php5\XP?@$classes/phing/util/regexp/Regexp.php5\X{d)classes/phing/util/PearPackageScanner.php!5\X! Y߶#classes/phing/util/StringHelper.php5 5\X5 Bs classes/phing/util/LogWriter.phpq 5\Xq 'classes/phing/util/DirectoryScanner.phpji5\Xji5˶(classes/phing/util/SourceFileScanner.phpm5\Xmme)classes/phing/util/ExtendedFileStream.phps5\Xsw纶 classes/phing/util/DataStore.php5\X%classes/phing/RuntimeConfigurable.php5\Xh( classes/phing/types/DataType.php5\X!classes/phing/types/Reference.phpV5\XV}!classes/phing/types/Parameter.php? 5\X? o'classes/phing/types/IterableFileSet.php5\X#classes/phing/types/TokenSource.php25\X2Nd()classes/phing/types/PhingFilterReader.php5\XҶ classes/phing/types/Excludes.php5\X ͚classes/phing/types/DirSet.php5\X ¶classes/phing/types/FileSet.php5\X$ֶ#classes/phing/types/FilterChain.php!5\X! %classes/phing/types/PropertyValue.php5\XHclasses/phing/types/Mapper.phpC$5\XC$i)classes/phing/types/RegularExpression.phpg5\Xge4*classes/phing/types/PearPackageFileSet.php5\XP_v'classes/phing/types/AbstractFileSet.phpN5\XN#classes/phing/types/Description.php5\XBضclasses/phing/types/Path.phpD@5\XD@T:"classes/phing/types/PatternSet.php>5\X>SY  classes/phing/types/FileList.php5\X-m3classes/phing/types/selectors/SelectorContainer.phpV5\XV*X51classes/phing/types/selectors/PresentSelector.php5\X2classes/phing/types/selectors/ContainsSelector.phpL5\XLyQ.classes/phing/types/selectors/DateSelector.php5\XOg/classes/phing/types/selectors/SelectorUtils.php!5\X!%1classes/phing/types/selectors/SelectorScanner.php5\Xg/classes/phing/types/selectors/DepthSelector.php5\X(.classes/phing/types/selectors/TypeSelector.phpS5\XSޢ4classes/phing/types/selectors/ExtendFileSelector.php5\XzҶ1classes/phing/types/selectors/MappingSelector.phpX5\XXh2classes/phing/types/selectors/FilenameSelector.php5\X;classes/phing/types/selectors/AbstractSelectorContainer.phpb)5\Xb)"d.classes/phing/types/selectors/SizeSelector.php$5\X$/:ȶ,classes/phing/types/selectors/OrSelector.phpG 5\XG g7.classes/phing/types/selectors/FileSelector.php}5\X}~p`-classes/phing/types/selectors/NotSelector.phpX5\XX4classes/phing/types/selectors/BaseExtendSelector.php+ 5\X+ C!h-classes/phing/types/selectors/AndSelector.php 5\X =&.classes/phing/types/selectors/NoneSelector.php, 5\X, 9P2classes/phing/types/selectors/MajoritySelector.phpc 5\Xc z~D.classes/phing/types/selectors/BaseSelector.php^ 5\X^ ="0classes/phing/types/selectors/DependSelector.phpf5\Xf7classes/phing/types/selectors/BaseSelectorContainer.php 5\X 2classes/phing/types/selectors/ReadableSelector.php5\Xt8classes/phing/types/selectors/ContainsRegexpSelector.php5\X8 0classes/phing/types/selectors/ExtendSelector.php5\Xu0classes/phing/types/selectors/SelectSelector.php5\X12classes/phing/types/selectors/WritableSelector.php5\Xr3classes/phing/types/selectors/DifferentSelector.phpU5\XU)c'classes/phing/types/Parameterizable.php?5\X?%#classes/phing/types/Commandline.php:5\X:~)classes/phing/types/ExcludesNameEntry.php5\Xo#classes/phing/types/TokenReader.php5\X"H'classes/phing/types/defaults.properties!5\X!M classes/phing/Diagnostics.php5\X )classes/phing/mappers/ContainerMapper.phpY5\XY!{S(classes/phing/mappers/FileNameMapper.php<5\X<(classes/phing/mappers/IdentityMapper.php5\X֛`)classes/phing/mappers/CompositeMapper.php5\XG&classes/phing/mappers/RegexpMapper.php~5\X~f^#$classes/phing/mappers/GlobMapper.php5\X#*classes/phing/mappers/FirstMatchMapper.php5\X3z'classes/phing/mappers/FlattenMapper.php5\XA'['classes/phing/mappers/ChainedMapper.php5\X9'classes/phing/mappers/CutDirsMapper.php5 5\X5 N(0%classes/phing/mappers/MergeMapper.phpI 5\XI Hclasses/phing/Project.php5\X>~ȶclasses/phing/BuildLogger.phpb 5\Xb GEcclasses/phing/BuildListener.php7 5\X7 =Ѷclasses/phing/Target.php&-5\X&-W޶"classes/phing/ProjectComponent.php" 5\X" Z؞ classes/phing/BuildException.phpa5\Xa`*classes/phing/Phing.php(5\X(<ضclasses/phing/Task.php5\Xsƶ classes/phing/UnknownElement.phpu 5\Xu bѶ&classes/phing/system/io/FileReader.php5\XU+classes/phing/system/io/FileInputStream.php 5\X bu&classes/phing/system/io/FileSystem.phpk5\Xksv *classes/phing/system/io/BufferedReader.phpp5\Xp:ܶ+classes/phing/system/io/WinNTFileSystem.php5\Xt+classes/phing/system/io/Win32FileSystem.phpF5\XF r*classes/phing/system/io/BufferedWriter.php 5\X ?n-classes/phing/system/io/InputStreamReader.php5\X9_(classes/phing/system/io/FilterReader.php5\X{$)classes/phing/system/io/IniFileParser.php 5\X H 2/classes/phing/system/io/FileParserInterface.php5\X*classes/phing/system/io/YamlFileParser.phpF5\XFauN(classes/phing/system/io/StringReader.php 5\X P&classes/phing/system/io/FileWriter.phpI5\XI-classes/phing/system/io/FileParserFactory.php`5\X`?3'classes/phing/system/io/InputStream.phpN5\XNx(*classes/phing/system/io/UnixFileSystem.php(5\X(µ<¶'classes/phing/system/io/IOException.php5\Xg>d%classes/phing/system/io/PhingFile.php5\XL"classes/phing/system/io/Writer.php5\X ,classes/phing/system/io/FileOutputStream.php 5\X \[.classes/phing/system/io/OutputStreamWriter.php 5\X <6classes/phing/system/io/FileParserFactoryInterface.php5\X])classes/phing/system/io/ConsoleReader.php 5\X e"'classes/phing/system/io/PrintStream.php 5\X ݶ(classes/phing/system/io/OutputStream.php5\X|o"classes/phing/system/io/Reader.php 5\X un&#classes/phing/system/util/Timer.php 5\X nIl&classes/phing/system/util/Register.php5\XR(classes/phing/system/util/Properties.php:$5\X:$ƶ3classes/phing/system/lang/FileNotFoundException.php_5\X_ 2classes/phing/system/lang/NullPointerException.php\5\X\Yɜ+/classes/phing/system/lang/SecurityException.phpY5\XYg)classes/phing/system/lang/EventObject.php5\XF'classes/phing/system/lang/Character.php5\X_Ҧclasses/phing/BuildEvent.php5\X>X bin/phing5\X bin/phing.bat5\X  bin/phing.php5\X`S%vendor/symfony/yaml/LICENSE)5\X)vendor/symfony/yaml/README.md5\Xԙe߶vendor/symfony/yaml/Dumper.php5\XM$vendor/symfony/yaml/phpunit.xml.dist5\X^!vendor/symfony/yaml/composer.json5\XхyU!vendor/symfony/yaml/Unescaper.phpQ5\XQ!+׶vendor/symfony/yaml/Inline.phpa5\Xavendor/symfony/yaml/Yaml.php5\X- vendor/symfony/yaml/Parser.php|5\X|K0vendor/symfony/yaml/Exception/ParseException.php] 5\X] A2vendor/symfony/yaml/Exception/RuntimeException.php5\X_q/vendor/symfony/yaml/Exception/DumpException.php5\X4vendor/symfony/yaml/Exception/ExceptionInterface.php5\X^KA vendor/symfony/yaml/CHANGELOG.md5\X#|Ӷvendor/symfony/yaml/Escaper.php5\X8Ǧ(vendor/symfony/yaml/Tests/InlineTest.phpa5\Xa@B0vendor/symfony/yaml/Tests/ParseExceptionTest.php5\XO&vendor/symfony/yaml/Tests/YamlTest.php5\XJ(vendor/symfony/yaml/Tests/ParserTest.phpgt5\Xgt9l1vendor/symfony/yaml/Tests/Fixtures/sfMergeKey.yml5\Xz0vendor/symfony/yaml/Tests/Fixtures/sfObjects.yml5\X<ö7vendor/symfony/yaml/Tests/Fixtures/YtsFoldedScalars.ymlz5\Xzګغ8vendor/symfony/yaml/Tests/Fixtures/escapedCharacters.yml5\X*,;vendor/symfony/yaml/Tests/Fixtures/YtsDocumentSeparator.yml5\Xc7vendor/symfony/yaml/Tests/Fixtures/YtsTypeTransfers.yml5\XB4.vendor/symfony/yaml/Tests/Fixtures/sfTests.yml 5\X //L¶5vendor/symfony/yaml/Tests/Fixtures/YtsAnchorAlias.yml[5\X[5R1vendor/symfony/yaml/Tests/Fixtures/embededPhp.yml5\XZܶ6vendor/symfony/yaml/Tests/Fixtures/YtsBlockMapping.yml5\X/vendor/symfony/yaml/Tests/Fixtures/sfQuotes.yml5\X+=<vendor/symfony/yaml/Tests/Fixtures/unindentedCollections.yml5\X+/N,vendor/symfony/yaml/Tests/Fixtures/index.yml85\X81vendor/symfony/yaml/Tests/Fixtures/sfComments.yml5\XO_}4vendor/symfony/yaml/Tests/Fixtures/YtsBasicTests.yml35\X3oL?vendor/symfony/yaml/Tests/Fixtures/YtsSpecificationExamples.ymlr5\Xra9q0vendor/symfony/yaml/Tests/Fixtures/sfCompact.ymlU 5\XU 9vendor/symfony/yaml/Tests/Fixtures/YtsFlowCollections.ymlX5\XXZ{kFvendor/symfony/yaml/Tests/Fixtures/multiple_lines_as_literal_block.yml65\X6U,vendor/symfony/yaml/Tests/Fixtures/arrow.gif5\X$9vendor/symfony/yaml/Tests/Fixtures/YtsNullsAndEmpties.yml5\X>;4vendor/symfony/yaml/Tests/Fixtures/YtsErrorTests.ymlq5\Xqtr(vendor/symfony/yaml/Tests/DumperTest.php-)5\X-)l@`vendor/composer/LICENSE35\X3fX!vendor/composer/autoload_psr4.php5\X5\X>DJ etc/log.xsl5\XNJ^etc/str.replace.function.xsl5\XM  etc/phpunit-frames.xslg5\Xgetc/coverage-frames.xsl5\X@䰬. */ /** * Abstract interface for objects which can contain tasks (targets) * Used to check if a class can contain tasks (via instanceof) * * @author Andreas Aderhold * @copyright 2001,2002 THYRELL. All rights reserved * * @package phing */ interface TaskContainer { /** * Adds a task to this task container. Must be implemented * by derived class * * @param Task $task The task to be added to the container. */ public function addTask(Task $task); } . * * @category Tasks * @package phing.tasks.ext * @author Paul Stuart * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) */ /** * Pull in Task class. */ require_once 'phing/Task.php'; /** * Executes Sass for a particular fileset. * * If the sass executable is not available, but scssphp is, then use that instead. * * @category Tasks * @package phing.tasks.ext * @author Paul Stuart * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @version Release: $Id: eb75e99660cf6fe49f68fe568e00aca4a193e31a $ * @link SassTask.php */ class SassTask extends Task { /** * Style to generate to. * * @var string */ protected $style = 'nested'; /** * Stack trace on error. * * @var bool */ protected $trace = false; /** * Unix-style newlines? * * @var bool */ protected $unixnewlines = true; /** * Encoding * * @var string */ protected $encoding = 'utf-8'; /** * SASS import path. * * @var string */ protected $loadPath = ''; /** * Whether to just check syntax * * @var bool */ protected $check = false; /** * Whether to use the sass command line tool. * * @var bool */ protected $useSass = true; /** * Whether to use the scssphp compiler, if available. * * @var bool */ protected $useScssphp = true; /** * Input filename if only processing one file is required. * * @var string|null */ protected $file = null; /** * Output filename * * @var string|null */ protected $output = null; /** * Scssphp compiler * * @var object */ protected $scssCompiler = null; /** * Contains the path info of our file to allow us to parse. * * @var array */ protected $pathInfo = null; /** * The Sass executable. * * @var string */ protected $executable = 'sass'; /** * The ext type we are looking for when Verifyext is set to true. * * More than likely should be "scss" or "sass". * * @var string */ protected $extfilter = ''; /** * This flag means 'note errors to the output, but keep going' * * @var bool */ protected $failonerror = true; /** * The fileset we will be running Sass on. * * @var array */ protected $filesets = array(); /** * Additional flags to pass to sass. * * @var string */ protected $flags = ''; /** * Indicates if we want to keep the directory structure of the files. * * @var bool */ protected $keepsubdirectories = true; /** * When true we will remove the current file ext. * * @var bool */ protected $removeoldext = true; /** * The new ext our files will have. * * @var string */ protected $newext = 'css'; /** * The path to send our output files to. * * If not defined they will be created in the same directory the * input is from. * * @var string */ protected $outputpath = ''; /** * Set input file (For example style.scss) * * Synonym for @see setFile * * @param string $file Filename * * @return void */ public function setInput($file) { $this->setFile($file); } /** * Set name of output file. * * @param string $file Filename of [css] to output. * * @return void */ public function setOutput($file) { $this->output = $file; } /** * Sets the failonerror flag. Default: true * * @param string $failonerror Jenkins style boolean value * * @access public * @return void */ public function setFailonerror($failonerror) { $this->failonerror = StringHelper::booleanValue($failonerror); } /** * Sets the executable to use for sass. Default: sass * * The default assumes sass is in your path. If not you can provide the full * path to sass. * * @param string $executable Name/path of sass executable * * @access public * @return void */ public function setExecutable($executable) { $this->executable = $executable; } /** * Return name/path of sass executable. * * @return string */ public function getExecutable() { return $this->executable; } /** * Sets the extfilter. Default: * * This will filter the fileset to only process files that match * this extension. This could also be done with the fileset. * * @param string $extfilter Extension to filter for. * * @access public * @return void */ public function setExtfilter($extfilter) { $this->extfilter = trim($extfilter, ' .'); } /** * Return extfilter setting. * * @return string */ public function getExtfilter() { return $this->extfilter; } /** * Additional flags to pass to sass. * * Command will be: * sass {$flags} {$inputfile} {$outputfile} * * @param string $flags List of flags accepted by sass. * * @access public * @return void */ public function setFlags($flags) { $this->flags = trim($flags); } /** * Return flags to be used when running the sass executable. * * @return string */ public function getFlags() { return trim($this->flags); } /** * Sets the removeoldext flag. Default: true * * This will cause us to strip the existing extension off the output * file. * * @param string $removeoldext Jenkins style boolean value * * @access public * @return void */ public function setRemoveoldext($removeoldext) { $this->removeoldext = StringHelper::booleanValue($removeoldext); } /** * Return removeoldext value (true/false) * * @return bool */ public function getRemoveoldext() { return $this->removeoldext; } /** * Set default encoding * * @param string $encoding Default encoding to use. * * @return void */ public function setEncoding($encoding) { $encoding = trim($encoding); if ($encoding !== '') { $this->flags .= " --default-encoding $encoding"; } else { $this->flags = str_replace( ' --default-encoding ' . $this->encoding, '', $this->flags ); } $this->encoding = $encoding; } /** * Return the output encoding. * * @return string */ public function getEncoding() { return $this->encoding; } /** * Sets the newext value. Default: css * * This is the extension we will add on to the output file regardless * of if we remove the old one or not. * * @param string $newext New extension to use, e.g. css * * @access public * @return void */ public function setNewext($newext) { $this->newext = trim($newext, ' .'); } /** * Return extension added to output files. * * @return string */ public function getNewext() { return $this->newext; } /** * Sets the outputpath value. Default: * * This will force the output path to be something other than * the path of the fileset used. * * @param string $outputpath Path name * * @access public * @return void */ public function setOutputpath($outputpath) { $this->outputpath = rtrim(trim($outputpath), DIRECTORY_SEPARATOR); } /** * Return the outputpath value. * * @return string */ public function getOutputpath() { return $this->outputpath; } /** * Sets the keepsubdirectories value. Default: true * * When set to true we will keep the directory structure. So any input * files in subdirectories will have their output file in that same * sub-directory. If false, all output files will be put in the path * defined by outputpath or in the directory top directory of the fileset. * * @param bool $keepsubdirectories Jenkins style boolean * * @access public * @return void */ public function setKeepsubdirectories($keepsubdirectories) { $this->keepsubdirectories = StringHelper::booleanValue($keepsubdirectories); } /** * Return keepsubdirectories value. * * @return bool */ public function getKeepsubdirectories() { return $this->keepsubdirectories; } /** * Nested creator, creates a FileSet for this task * * @return FileSet The created fileset object */ public function createFileSet() { $num = array_push($this->filesets, new FileSet()); return $this->filesets[$num - 1]; } /** * Whether to just check syntax. * * @param string $value Jenkins style boolean value * * @return void */ public function setCheck($value) { $check = StringHelper::booleanValue($value); $this->check = $check; if ($check) { $this->flags .= ' --check '; } else { $this->flags = str_replace(' --check ', '', $this->flags); } } /** * Indicate if just a syntax check is required. * * @return boolean */ public function getCheck() { return $this->check; } /** * Set style to compact * * @param string $value Jenkins style boolean value * * @return void */ public function setCompact($value) { $compress = StringHelper::booleanValue($value); if ($compress) { $this->flags = str_replace(' --style ' . $this->style, '', $this->flags); $this->flags .= ' --style compact'; $this->style = 'compact'; } } /** * Indicate whether style is set to 'coompact'. * * @return bool * @see setCompact */ public function getCompact() { return $this->style === 'compact'; } /** * Set style to compressed * * @param string $value Jenkins style boolean value * * @return void */ public function setCompressed($value) { $compress = StringHelper::booleanValue($value); if ($compress) { $this->flags = str_replace(' --style ' . $this->style, '', $this->flags); $this->flags .= ' --style compressed'; $this->style = 'compressed'; } } /** * Indicate whether style is set to 'compressed'. * * @return bool * @see setCompressed */ public function getCompressed() { return $this->style === 'compressed'; } /** * Set style to crunched. Supported by scssphp only. * * @param string $value Jenkins style boolean value * * @return void */ public function setCrunched($value) { $compress = StringHelper::booleanValue($value); if ($compress) { $this->style = 'crunched'; } } /** * Indicate whether style is set to 'crunched'. * * @return bool * @see setCrunched */ public function getCrunched() { return $this->style === 'crunched'; } /** * Set style to expanded * * @param string $value Jenkins style boolean value * * @return void */ public function setExpand($value) { $expand = StringHelper::booleanValue($value); if ($expand) { $this->flags = str_replace(' --style ' . $this->style, '', $this->flags); $this->flags .= ' --style expanded'; $this->style = 'expanded'; } } /** * Indicate whether style is set to 'expanded'. * * @return bool * @see setExpand */ public function getExpand() { return $this->style === 'expanded'; } /** * Set style to nested * * @param string $value Jenkins style boolean value * * @return void */ public function setNested($value) { $nested = StringHelper::booleanValue($value); if ($nested) { $this->flags = str_replace(' --style ' . $this->style, '', $this->flags); $this->flags .= ' --style nested'; $this->style = 'nested'; } } /** * Indicate whether style is set to 'nested'. * * @return bool * @see setNested */ public function getNested() { return $this->style === 'nested'; } /** * Whether to force recompiled when --update is used. * * @param string $value Jenkins style boolean value * * @return void */ public function setForce($value) { $force = StringHelper::booleanValue($value); $this->force = $force; if ($force) { $this->flags .= ' --force '; } else { $this->flags = str_replace(' --force ', '', $this->flags); } } /** * Return force value. * * @return bool */ public function getForce() { return $this->force; } /** * Whether to cache parsed sass files. * * @param string $value Jenkins style boolean value * * @return void */ public function setNoCache($value) { $noCache = StringHelper::booleanValue($value); $this->noCache = $noCache; if ($noCache) { $this->flags .= ' --no-cache '; } else { $this->flags = str_replace(' --no-cache ', '', $this->flags); } } /** * Return noCache value. * * @return bool */ public function getNoCache() { return $this->noCache; } /** * Specify SASS import path * * @param string $path Import path. * * @return void */ public function setPath($path) { $this->flags .= "--load-path $path"; $this->loadPath = $path; } /** * Return the SASS import path. * * @return string */ public function getPath() { return $this->loadPath; } /** * Set output style. * * @param mixed $style Style. * * @return void */ public function setStyle($style) { $style = strtolower($style); switch($style) { case 'nested': case 'compact': case 'compressed': case 'expanded': case 'crunched': $this->flags = str_replace(" --style $this->style", '', $this->flags); $this->style = $style; $this->flags .= " --style $style"; break; default: $this->log("Style $style ignored", Project::MSG_INFO); } } /** * Return style used for generating output. * * @return string */ public function getStyle() { return $this->style; } /** * Set trace option. * * IE: Whether to output a stack trace on error. * * @param string $trace Jenkins style boolean value * * @return void */ public function setTrace($trace) { $this->trace = StringHelper::booleanValue($trace); if ($this->trace) { $this->flags .= ' --trace '; } else { $this->flags = str_replace(' --trace ', '', $this->flags); } } /** * Return trace option. * * @return bool */ public function getTrace() { return $this->trace; } /** * Whether to use unix-style newlines. * * @param string $newlines Jenkins style boolean value * * @return void */ public function setUnixnewlines($newlines) { $unixnewlines = StringHelper::booleanValue($newlines); $this->unixnewlines = $unixnewlines; if ($unixnewlines) { $this->flags .= ' --unix-newlines '; } else { $this->flags = str_replace(' --unix-newlines ', '', $this->flags); } } /** * Return unix-newlines setting * * @return bool */ public function getUnixnewlines() { return $this->unixnewlines; } /** * Whether to identify source-file and line number for generated CSS. * * @param string $lineNumbers Jenkins style boolean value * * @return void */ public function setLineNumbers($lineNumbers) { $lineNumbers = StringHelper::booleanValue($lineNumbers); $this->lineNumbers = $lineNumbers; if ($lineNumbers) { $this->flags .= ' --line-numbers '; } else { $this->flags = str_replace(' --line-numbers ', '', $this->flags); } } /** * Return line-numbers setting. * * @return bool */ public function getLineNumbers() { return $this->lineNumbers; } /** * Whether to use the 'sass' command line tool. * * @param string $value Jenkins style boolean value. * * @return void * @link http://sass-lang.com/install */ public function setUseSass($value) { $this->useSass = StringHelper::booleanValue($value); } /** * Whether to use the scssphp compiler. * * @param string $value Jenkins style boolean value. * * @return void * @link http://leafo.github.io/scssphp/ */ public function setUseScssphp($value) { $this->useScssphp = StringHelper::booleanValue($value); if (version_compare(PHP_VERSION, '5.2', '<=')) { $this->useScssphp = false; $this->log( "SCSSPHP is incompatible with this version of PHP", Project::MSG_INFO ); } } /** * Set single filename to compile from scss to css. * * @param string $file Single filename to compile. * * @return void */ public function setFile($file) { $this->file = $file; } /** * Init: pull in the PEAR System class * * @access public * @return void */ public function init() { @include_once 'System.php'; if (!class_exists('System')) { throw new BuildException("You must have installed PEAR in order to use SassTask."); } @include_once 'vendor/autoload.php'; if (version_compare(PHP_VERSION, '5.2', '<=')) { $this->useScssphp = false; $this->log( "SCSSPHP is incompatible with this version of PHP", Project::MSG_INFO ); } } /** * Our main execution of the task. * * @throws BuildException * @throws Exception * * @access public * @return void */ public function main() { if ($this->useSass) { if (strlen($this->executable) < 0) { throw new BuildException("'executable' must be defined."); } } if (empty($this->filesets) && $this->file === null) { throw new BuildException( "Missing either a nested fileset or attribute 'file'" ); } // If both are set to be used, prefer sass over scssphp. $lUseScssphp = false; if ($this->useSass && $this->useScssphp) { if (System::which($this->executable) === false) { if ($this->loadScssphp() === false) { $msg = sprintf( "%s not found. Install sass or leafo scssphp.", $this->executable ); if ($this->failonerror) { throw new BuildException($msg); } else { $this->log($msg, Project::MSG_ERR); return; } } else { $lUseScssphp = true; $this->scssCompiler = $this->initialiseScssphp(); } } } elseif (!$this->useSass && !$this->useScssphp) { $this->log( "Neither sass nor scssphp are to be used.", Project::MSG_ERR ); return; } elseif ($this->useSass) { if (System::which($this->executable) === false) { $msg = sprintf( "%s not found. Install sass.", $this->executable ); if ($this->failonerror) { throw new BuildException($msg); } else { $this->log($msg, Project::MSG_ERR); return; } } } elseif ($this->useScssphp) { if ($this->loadScssphp() === false) { $msg = sprintf( "Install leafo scssphp." ); if ($this->failonerror) { throw new BuildException($msg); } else { $this->log($msg, Project::MSG_ERR); return; } } else { $lUseScssphp = true; $this->scssCompiler = $this->initialiseScssphp(); } } if (count($this->filesets) > 0) { $this->processFilesets($lUseScssphp); } elseif ($this->file !== null) { $this->processFile($lUseScssphp); } } /** * Compile a specified file. * * If output file is not specified, but outputpath is, place output in * that directory. If neither is specified, place .css file in the * directory that the input file is in. * * @param boolean $useScssphp Whether to use the scssphp compiler. * * @return void */ public function processFile($useScssphp) { $this->log("Process file", Project::MSG_INFO); if (is_null($this->output)) { $specifiedOutputPath = (strlen($this->outputpath) > 0); if ($specifiedOutputPath === false) { $info = pathinfo($this->file); $path = $info['dirname']; $this->outputpath = $path; } else { $path = $this->outputpath; } $output = $path . DIRECTORY_SEPARATOR . $info['filename']; if (!$this->removeoldext) { $output .= '.' . $this->pathInfo['extension']; } if (strlen($this->newext) > 0) { $output .= '.' . $this->newext; } $this->output = $output; } else { $output = $this->output; } $this->compile($this->file, $output, $useScssphp); } /** * Process filesets - compiling/generating css files as required. * * @param boolean $useScssphp Whether to use the scssphp compiler. * * @return void */ public function processFilesets($useScssphp) { foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($this->project); $files = $ds->getIncludedFiles(); $dir = $fs->getDir($this->project)->getPath(); // If output path isn't defined then set it to the path of our fileset. $specifiedOutputPath = (strlen($this->outputpath) > 0); if ($specifiedOutputPath === false) { $this->outputpath = $dir; } foreach ($files as $file) { $fullFilePath = $dir . DIRECTORY_SEPARATOR . $file; $this->pathInfo = pathinfo($file); $run = true; switch(strtolower($this->pathInfo['extension'])) { case 'scss': case 'sass': break; default: $this->log('Ignoring ' . $file, Project::MSG_DEBUG); $run = false; } if ($run && ($this->extfilter === '' || $this->extfilter === $this->pathInfo['extension']) ) { $outputFile = $this->buildOutputFilePath(); $this->compile($fullFilePath, $outputFile, $useScssphp); } } } } /** * Compile * * @param string $fullFilePath Fully qualified filename to compile. * @param string $outputFile Filename for generated css. * @param boolean $lUseScssphp Whether to use scssphp compiler. * * @return void */ public function compile($fullFilePath, $outputFile, $lUseScssphp) { $output = null; if (!$lUseScssphp) { try { $output = $this->executeCommand( $fullFilePath, $outputFile ); if ($this->failonerror && $output[0] !== 0) { throw new BuildException( "Result returned as not 0. Result: {$output[0]}", Project::MSG_INFO ); } } catch (Exception $e) { if ($this->failonerror) { throw $e; } else { $this->log( "Result: {$output[0]}", Project::MSG_INFO ); } } } else { $this->log( sprintf("Compiling '%s' via scssphp", $fullFilePath), Project::MSG_INFO ); $input = file_get_contents($fullFilePath); try { $out = $this->scssCompiler->compile($input, $fullFilePath); if ($out !== '') { $success = file_put_contents($outputFile, $out); if ($success) { $this->log( sprintf( "'%s' compiled and written to '%s'", $fullFilePath, $outputFile ), Project::MSG_VERBOSE ); } } else { $this->log('Compilation resulted in empty string'); } } catch (Exception $ex) { if ($this->failonerror) { throw new BuildException($ex->getMessage()); } else { $this->log($ex->getMessage(), Project::MSG_ERR); } } } } /** * Builds the full path to the output file based on our settings. * * @return string * * @access protected */ protected function buildOutputFilePath() { $outputFile = $this->outputpath.DIRECTORY_SEPARATOR; $subpath = trim($this->pathInfo['dirname'], ' .'); if ($this->keepsubdirectories === true && strlen($subpath) > 0) { $outputFile .= $subpath . DIRECTORY_SEPARATOR; } $outputFile .= $this->pathInfo['filename']; if (!$this->removeoldext) { $outputFile .= '.' . $this->pathInfo['extension']; } if (strlen($this->newext) > 0) { $outputFile .= '.' . $this->newext; } return $outputFile; } /** * Executes the command and returns return code and output. * * @param string $inputFile Input file * @param string $outputFile Output file * * @access protected * @throws BuildException * @return array array(return code, array with output) */ protected function executeCommand($inputFile, $outputFile) { // Prevent over-writing existing file. if ($inputFile == $outputFile) { throw new BuildException('Input file and output file are the same!'); } $output = array(); $return = null; $fullCommand = $this->executable; if (strlen($this->flags) > 0) { $fullCommand .= " {$this->flags}"; } $fullCommand .= " {$inputFile} {$outputFile}"; $this->log("Executing: {$fullCommand}", Project::MSG_INFO); exec($fullCommand, $output, $return); return array($return, $output); } /** * Pull in scssphp package, return true if successful. * * @return bool */ public function loadScssphp() { $success = @include_once "vendor/leafo/scssphp/scss.inc.php"; if ($success === false) { $success = @include_once "scssphp/scss.inc.php"; } return $success; } /** * Get ScssPhp Compiler. * * @return Leafo\ScssPhp\Compiler */ public function getNewCompiler() { // Instantiate the class in a way that is compatible with // PHP 5.2 up to 7.x. $compiler = '\\Leafo\\ScssPhp\\Compiler'; return new $compiler; } /** * Initialise and return an instance of the ScssPhp Compiler. * * @return Leafo\ScssPhp\Compiler */ public function initialiseScssphp() { $scss = $this->getNewCompiler(); if ($this->style) { $ucStyle = ucfirst(strtolower($this->style)); $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . $ucStyle); } if ($this->encoding) { $scss->setEncoding($this->encoding); } if ($this->lineNumbers) { $scss->setLineNumberStyle(1); } if ($this->loadPath !== '') { $scss->setImportPaths(explode(PATH_SEPARATOR, $this->loadPath)); } return $scss; } } . */ require_once 'phing/Task.php'; /** * ApiGen task (http://apigen.org). * * @package phing.tasks.ext.apigen * @author Martin Srank * @author Jaroslav Hanslík * @author Lukáš Homza * @since 2.4.10 */ class ApiGenTask extends Task { /** * Default ApiGen executable name. * * @var string */ private $executable = 'apigen'; /** * Default ApiGen action. * * @var string */ private $action = 'generate'; /** * Default ApiGen options. * * @var string */ private $options = array(); /** * Sets the ApiGen executable name. * * @param string $executable */ public function setExecutable($executable) { $this->executable = (string) $executable; } /** * Sets the ApiGen action to be executed. * * @param string $action */ public function setAction($action) { $this->action = (string) $action; } /** * Sets the config file name. * * @param string $config */ public function setConfig($config) { $this->options['config'] = (string) $config; } /** * Sets source files or directories. * * @param string $source */ public function setSource($source) { $this->options['source'] = explode(',', $source); } /** * Sets the destination directory. * * @param string $destination */ public function setDestination($destination) { $this->options['destination'] = (string) $destination; } /** * Sets list of allowed file extensions. * * @param string $extensions */ public function setExtensions($extensions) { $this->options['extensions'] = explode(',', $extensions); } /** * Sets masks (case sensitive) to exclude files or directories from processing. * * @param string $exclude */ public function setExclude($exclude) { $this->options['exclude'] = explode(',', $exclude); } /** * Sets masks to exclude elements from documentation generating. * * @param string $skipDocPath */ public function setSkipDocPath($skipDocPath) { $this->options['skip-doc-path'] = explode(',', $skipDocPath); } /** * Sets the character set of source files. * * @param string $charset */ public function setCharset($charset) { $this->options['charset'] = explode(',', $charset); } /** * Sets the main project name prefix. * * @param string $main */ public function setMain($main) { $this->options['main'] = (string) $main; } /** * Sets the title of generated documentation. * * @param string $title */ public function setTitle($title) { $this->options['title'] = (string) $title; } /** * Sets the documentation base URL. * * @param string $baseUrl */ public function setBaseUrl($baseUrl) { $this->options['base-url'] = (string) $baseUrl; } /** * Sets the Google Custom Search ID. * * @param string $googleCseId */ public function setGoogleCseId($googleCseId) { $this->options['google-cse-id'] = (string) $googleCseId; } /** * Sets the Google Custom Search label. * * @param string $googleCseLabel */ public function setGoogleCseLabel($googleCseLabel) { $this->options['google-cse-label'] = (string) $googleCseLabel; } /** * Sets the Google Analytics tracking code. * * @param string $googleAnalytics */ public function setGoogleAnalytics($googleAnalytics) { $this->options['google-analytics'] = (string) $googleAnalytics; } /** * Sets the template config file name. * * @param string $templateConfig */ public function setTemplateConfig($templateConfig) { $this->options['template-config'] = (string) $templateConfig; } /** * Sets the template config file name. * * @param string $templateTheme */ public function setTemplateTheme($templateTheme) { $this->options['template-theme'] = (string) $templateTheme; } /** * Sets how elements should be grouped in the menu. * * @param string $groups */ public function setGroups($groups) { $this->options['groups'] = (string) $groups; } /** * Sets the element access levels. * * Documentation only for methods and properties with the given access level will be generated. * * @param string $accessLevels */ public function setAccessLevels($accessLevels) { $this->options['access-levels'] = (string) $accessLevels; } /** * Sets the element access levels. * * Documentation only for methods and properties with the given access level will be generated. * * @param string $annotationGroups */ public function setAnnotationGroups($annotationGroups) { $this->options['annotation-groups'] = (string) $annotationGroups; } /** * Sets if documentation for elements marked as internal and internal documentation parts should be generated. * * @param boolean $internal */ public function setInternal($internal) { if((bool) $internal) { $this->options['internal'] = null; } } /** * Sets if documentation for PHP internal classes should be generated. * * @param boolean $php */ public function setPhp($php) { if((bool) $php) { $this->options['php'] = null; } } /** * Sets if tree view of classes, interfaces, traits and exceptions should be generated. * * @param boolean $tree */ public function setTree($tree) { if((bool) $tree) { $this->options['tree'] = null; } } /** * Sets if documentation for deprecated elements should be generated. * * @param boolean $deprecated */ public function setDeprecated($deprecated) { if((bool) $deprecated) { $this->options['deprecated'] = null; } } /** * Sets if documentation of tasks should be generated. * * @param boolean $todo */ public function setTodo($todo) { if((bool) $todo) { $this->options['todo'] = null; } } /** * Sets if highlighted source code files should be generated. * * @param boolean $noSourceCode */ public function setSourceCode($noSourceCode) { if(!((bool) $noSourceCode)) { $this->options['no-source-code'] = null; } } /** * Sets if highlighted source code files should not be generated. * * @deprecated * @param boolean $noSourceCode */ public function setNoSourceCode($noSourceCode) { $this->setSourceCode(!$noSourceCode); } /** * Sets if a link to download documentation as a ZIP archive should be generated. * * @param boolean $download */ public function setDownload($download) { if((bool) $download) { $this->options['download'] = null; } } /** * Enables/disables the debug mode. * * @param boolean $debug */ public function setDebug($debug) { if((bool) $debug) { $this->options['debug'] = null; } } /** * Runs ApiGen. * * @throws BuildException If something is wrong. * @see Task::main() */ public function main() { if ('apigen' !== $this->executable && !is_file($this->executable)) { throw new BuildException(sprintf('Executable %s not found', $this->executable), $this->getLocation()); } if (!empty($this->options['config'])) { // Config check if (!is_file($this->options['config'])) { throw new BuildException(sprintf( 'Config file %s doesn\'t exist', $this->options['config'] ), $this->getLocation()); } } else { // Source check if (empty($this->options['source'])) { throw new BuildException('Source is not set', $this->getLocation()); } // Destination check if (empty($this->options['destination'])) { throw new BuildException('Destination is not set', $this->getLocation()); } } // Source check if (!empty($this->options['source'])) { foreach ($this->options['source'] as $source) { if (!file_exists($source)) { throw new BuildException(sprintf('Source %s doesn\'t exist', $source), $this->getLocation()); } } } // Execute ApiGen exec(escapeshellcmd($this->executable) . ' ' . escapeshellcmd($this->action) . ' ' . $this->constructArguments(), $output, $return); $logType = 0 === $return ? Project::MSG_INFO : Project::MSG_ERR; foreach ($output as $line) { $this->log($line, $logType); } } /** * Generates command line arguments for the ApiGen executable. * * @return string */ protected function constructArguments() { $args = array(); foreach ($this->options as $option => $value) { if (is_bool($value)) { $args[] = '--' . $option . '=' . ($value ? 'yes' : 'no'); } elseif (is_array($value)) { foreach ($value as $v) { $args[] = '--' . $option . '=' . escapeshellarg($v); } } else { $args[] = '--' . $option . '=' . escapeshellarg($value); } } return implode(' ', $args); } } . */ require_once 'phing/Task.php'; include_once 'phing/types/Reference.php'; /** * Handles Creole configuration needed by SQL type tasks. * * @author Hans Lellelid (Phing) * @author Nick Chalko (Ant) * @author Jeff Martin (Ant) * @author Michael McCallum (Ant) * @author Tim Stephenson (Ant) * @version $Id: b020d667f8bb1d09d43607ffaa4ff6e33bd91dbd $ * @package phing.tasks.system */ abstract class CreoleTask extends Task { /** * Used for caching loaders / driver. This is to avoid * getting an OutOfMemoryError when calling this task * multiple times in a row. * * NOT IMPLEMENTED YET */ private static $loaderMap = array(); private $caching = true; /** * Autocommit flag. Default value is false */ private $autocommit = false; /** * [optional] Classpath to Creole driver to use. * @param string */ private $driver; /** * DB url. */ private $url; /** * User name. */ private $userId; /** * Password */ private $password; /** * RDBMS Product needed for this SQL. **/ private $rdbms; /** * Initialize CreoleTask. * This method includes any necessary Creole libraries and triggers * appropriate error if they cannot be found. This is not done in header * because we may want this class to be loaded w/o triggering an error. */ public function init() { include_once 'creole/Creole.php'; if (!class_exists('Creole')) { throw new Exception("Creole task depends on Creole classes being on include_path. (i.e. include of 'creole/Creole.php' failed.)"); } } /** * Caching loaders / driver. This is to avoid * getting an OutOfMemoryError when calling this task * multiple times in a row; default: true * @param bool $enable */ public function setCaching($enable) { $this->caching = $enable; } /** * Sets the database connection URL; required. * @param string $url */ public function setUrl($url) { $this->url = $url; } /** * Set the Creole driver to be used. * * @param string $driver driver class name */ public function setDriver($driver) { $this->driver = $driver; } /** * Sets the password; required. * @param string $password The password to set */ public function setPassword($password) { $this->password = $password; } /** * Auto commit flag for database connection; * optional, default false. * * @param bool $autocommit The autocommit to set */ public function setAutocommit($autocommit) { $this->autocommit = $autocommit; } /** * Sets the version string, execute task only if * rdbms version match; optional. * * @param string $version */ public function setVersion($version) { $this->version = $version; } /** * @return array */ protected function getLoaderMap() { return self::$loaderMap; } /** * Creates a new Connection as using the driver, url, userid and password specified. * The calling method is responsible for closing the connection. * * @return Connection the newly created connection. * * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load. */ protected function getConnection() { if ($this->url === null) { throw new BuildException("Url attribute must be set!", $this->location); } try { $this->log("Connecting to " . $this->getUrl(), Project::MSG_VERBOSE); $info = new Properties(); $dsn = Creole::parseDSN($this->url); if (!isset($dsn["username"]) && $this->userId === null) { throw new BuildException("Username must be in URL or userid attribute must be set.", $this->location); } if ($this->userId) { $dsn["username"] = $this->getUserId(); } if ($this->password) { $dsn["password"] = $this->getPassword(); } if ($this->driver) { Creole::registerDriver($dsn['phptype'], $this->driver); } $conn = Creole::getConnection($dsn); $conn->setAutoCommit($this->autocommit); return $conn; } catch (SQLException $e) { throw new BuildException($e->getMessage(), $this->location); } } /** * @param $value */ public function isCaching($value) { $this->caching = $value; } /** * Gets the autocommit. * @return Returns a boolean */ public function isAutocommit() { return $this->autocommit; } /** * Gets the url. * * @return string */ public function getUrl() { return $this->url; } /** * Gets the userId. * * @return string */ public function getUserId() { return $this->userId; } /** * Set the user name for the connection; required. * @param string $userId */ public function setUserid($userId) { $this->userId = $userId; } /** * Gets the password. * @return string */ public function getPassword() { return $this->password; } } . */ require_once 'phing/tasks/ext/creole/CreoleTask.php'; include_once 'phing/system/io/StringReader.php'; /** * Executes a series of SQL statements on a database using Creole. * *

Statements can * either be read in from a text file using the src attribute or from * between the enclosing SQL tags.

* *

Multiple statements can be provided, separated by semicolons (or the * defined delimiter). Individual lines within the statements can be * commented using either --, // or REM at the start of the line.

* *

The autocommit attribute specifies whether auto-commit should be * turned on or off whilst executing the statements. If auto-commit is turned * on each statement will be executed and committed. If it is turned off the * statements will all be executed as one transaction.

* *

The onerror attribute specifies how to proceed when an error occurs * during the execution of one of the statements. * The possible values are: continue execution, only show the error; * stop execution and commit transaction; * and abort execution and transaction and fail task.

* * @author Hans Lellelid (Phing) * @author Jeff Martin (Ant) * @author Michael McCallum (Ant) * @author Tim Stephenson (Ant) * @package phing.tasks.ext.creole * @version $Id: b0540d6f531fdc2a5103a09c92a54318ebdf8c0b $ */ class CreoleSQLExecTask extends CreoleTask { private $goodSql = 0; private $totalSql = 0; const DELIM_ROW = "row"; const DELIM_NORMAL = "normal"; /** * Database connection */ private $conn = null; /** * files to load */ private $filesets = array(); /** * all filterchains objects assigned to this task */ private $filterChains = array(); /** * SQL statement */ private $statement = null; /** * SQL input file */ private $srcFile = null; /** * SQL input command */ private $sqlCommand = ""; /** * SQL transactions to perform */ private $transactions = array(); /** * SQL Statement delimiter */ private $delimiter = ";"; /** * The delimiter type indicating whether the delimiter will * only be recognized on a line by itself */ private $delimiterType = "normal"; // can't use constant just defined /** * Print SQL results. */ private $print = false; /** * Print header columns. */ private $showheaders = true; /** * Results Output file. */ private $output = null; /** * Action to perform if an error is found **/ private $onError = "abort"; /** * Encoding to use when reading SQL statements from a file */ private $encoding = null; /** * Append to an existing file or overwrite it? */ private $append = false; /** * Set the name of the SQL file to be run. * Required unless statements are enclosed in the build file * @param PhingFile $srcFile */ public function setSrc(PhingFile $srcFile) { $this->srcFile = $srcFile; } /** * Set an inline SQL command to execute. * NB: Properties are not expanded in this text. * @param $sql */ public function addText($sql) { $this->sqlCommand .= $sql; } /** * Adds a set of files (nested fileset attribute). * @param FileSet $set */ public function addFileset(FileSet $set) { $this->filesets[] = $set; } /** * Creates a filterchain * * @return object The created filterchain object */ public function createFilterChain() { $num = array_push($this->filterChains, new FilterChain($this->project)); return $this->filterChains[$num - 1]; } /** * Add a SQL transaction to execute */ public function createTransaction() { $t = new SQLExecTransaction($this); $this->transactions[] = $t; return $t; } /** * Set the file encoding to use on the SQL files read in * * @param the $encoding * @internal param the $encoding encoding to use on the files */ public function setEncoding($encoding) { $this->encoding = $encoding; } /** * Set the statement delimiter. * *

For example, set this to "go" and delimitertype to "ROW" for * Sybase ASE or MS SQL Server.

* * @param delimiter */ public function setDelimiter($delimiter) { $this->delimiter = $delimiter; } /** * Set the Delimiter type for this sql task. The delimiter type takes two * values - normal and row. Normal means that any occurrence of the delimiter * terminate the SQL command whereas with row, only a line containing just * the delimiter is recognized as the end of the command. * * @param string $delimiterType */ public function setDelimiterType($delimiterType) { $this->delimiterType = $delimiterType; } /** * Set the print flag. * * @param boolean $print */ public function setPrint($print) { $this->print = (boolean) $print; } /** * Print headers for result sets from the * statements; optional, default true. * @param boolean $showheaders */ public function setShowheaders($showheaders) { $this->showheaders = (boolean) $showheaders; } /** * Set the output file; * optional, defaults to the console. * @param PhingFile $output */ public function setOutput(PhingFile $output) { $this->output = $output; } /** * whether output should be appended to or overwrite * an existing file. Defaults to false. * @param $append */ public function setAppend($append) { $this->append = (boolean) $append; } /** * Action to perform when statement fails: continue, stop, or abort * optional; default "abort" * @param $action */ public function setOnerror($action) { $this->onError = $action; } /** * Load the sql file and then execute it * @throws BuildException */ public function main() { $savedTransaction = array(); for ($i = 0, $size = count($this->transactions); $i < $size; $i++) { $savedTransaction[] = clone $this->transactions[$i]; } $savedSqlCommand = $this->sqlCommand; $this->sqlCommand = trim($this->sqlCommand); try { if ($this->srcFile === null && $this->sqlCommand === "" && empty($this->filesets) ) { if (count($this->transactions) === 0) { throw new BuildException("Source file or fileset, " . "transactions or sql statement " . "must be set!", $this->location); } } if ($this->srcFile !== null && !$this->srcFile->exists()) { throw new BuildException("Source file does not exist!", $this->location); } // deal with the filesets for ($i = 0, $size = count($this->filesets); $i < $size; $i++) { $fs = $this->filesets[$i]; $ds = $fs->getDirectoryScanner($this->project); $srcDir = $fs->getDir($this->project); $srcFiles = $ds->getIncludedFiles(); // Make a transaction for each file for ($j = 0, $size = count($srcFiles); $j < $size; $j++) { $t = $this->createTransaction(); $t->setSrc(new PhingFile($srcDir, $srcFiles[$j])); } } // Make a transaction group for the outer command $t = $this->createTransaction(); if ($this->srcFile) { $t->setSrc($this->srcFile); } $t->addText($this->sqlCommand); $this->conn = $this->getConnection(); try { $this->statement = $this->conn->createStatement(); $out = null; try { if ($this->output !== null) { $this->log("Opening output file " . $this->output, Project::MSG_VERBOSE); $out = new BufferedWriter(new FileWriter($this->output->getAbsolutePath(), $this->append)); } // Process all transactions for ($i = 0, $size = count($this->transactions); $i < $size; $i++) { $this->transactions[$i]->runTransaction($out); if (!$this->isAutocommit()) { $this->log("Committing transaction", Project::MSG_VERBOSE); $this->conn->commit(); } } if ($out) { $out->close(); } } catch (Exception $e) { if ($out) { $out->close(); } throw $e; } } catch (IOException $e) { if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { try { $this->conn->rollback(); } catch (SQLException $ex) { } } throw new BuildException($e->getMessage(), $this->location); } catch (SQLException $e) { if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") { try { $this->conn->rollback(); } catch (SQLException $ex) { } } throw new BuildException($e->getMessage(), $this->location); } $this->log( $this->goodSql . " of " . $this->totalSql . " SQL statements executed successfully" ); } catch (Exception $e) { $this->transactions = $savedTransaction; $this->sqlCommand = $savedSqlCommand; throw $e; } // finally { $this->transactions = $savedTransaction; $this->sqlCommand = $savedSqlCommand; } /** * read in lines and execute them * @param Reader $reader * @param null $out * @throws BuildException */ public function runStatements(Reader $reader, $out = null) { $sql = ""; $line = ""; $buffer = ''; if ((is_array($this->filterChains)) && (!empty($this->filterChains))) { $in = FileUtils::getChainedReader(new BufferedReader($reader), $this->filterChains, $this->getProject()); while (-1 !== ($read = $in->read())) { // -1 indicates EOF $buffer .= $read; } $lines = explode("\n", $buffer); } else { $in = new BufferedReader($reader); while (($line = $in->readLine()) !== null) { $lines[] = $line; } } try { foreach ($lines as $line) { $line = trim($line); $line = ProjectConfigurator::replaceProperties( $this->project, $line, $this->project->getProperties() ); if (StringHelper::startsWith("//", $line) || StringHelper::startsWith("--", $line) || StringHelper::startsWith("#", $line) ) { continue; } if (strlen($line) > 4 && strtoupper(substr($line, 0, 4)) == "REM " ) { continue; } $sql .= " " . $line; $sql = trim($sql); // SQL defines "--" as a comment to EOL // and in Oracle it may contain a hint // so we cannot just remove it, instead we must end it if (strpos($line, "--") !== false) { $sql .= "\n"; } if ($this->delimiterType == self::DELIM_NORMAL && StringHelper::endsWith($this->delimiter, $sql) || $this->delimiterType == self::DELIM_ROW && $line == $this->delimiter ) { $this->log("SQL: " . $sql, Project::MSG_VERBOSE); $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)), $out); $sql = ""; } } // Catch any statements not followed by ; if ($sql !== "") { $this->execSQL($sql, $out); } } catch (SQLException $e) { throw new BuildException("Error running statements", $e); } } /** * Exec the sql statement. * @param $sql * @param null $out * @throws BuildException */ protected function execSQL($sql, $out = null) { // Check and ignore empty statements if (trim($sql) == "") { return; } try { $this->totalSql++; if (!$this->statement->execute($sql)) { $this->log($this->statement->getUpdateCount() . " rows affected", Project::MSG_VERBOSE); } else { if ($this->print) { $this->printResults($out); } } $this->goodSql++; } catch (SQLException $e) { $this->log("Failed to execute: " . $sql, Project::MSG_ERR); if ($this->onError != "continue") { throw new BuildException("Failed to execute SQL", $e); } $this->log($e->getMessage(), Project::MSG_ERR); } } /** * print any results in the statement. * @param null $out */ protected function printResults($out = null) { $rs = null; do { $rs = $this->statement->getResultSet(); if ($rs !== null) { $this->log("Processing new result set.", Project::MSG_VERBOSE); $line = ""; $colsprinted = false; while ($rs->next()) { $fields = $rs->getRow(); if (!$colsprinted && $this->showheaders) { $first = true; foreach ($fields as $fieldName => $ignore) { if ($first) { $first = false; } else { $line .= ","; } $line .= $fieldName; } if ($out !== null) { $out->write($line); $out->newLine(); } else { print($line . PHP_EOL); } $line = ""; $colsprinted = true; } // if show headers $first = true; foreach ($fields as $columnValue) { if ($columnValue != null) { $columnValue = trim($columnValue); } if ($first) { $first = false; } else { $line .= ","; } $line .= $columnValue; } if ($out !== null) { $out->write($line); $out->newLine(); } else { print($line . PHP_EOL); } $line = ""; } // while rs->next() } } while ($this->statement->getMoreResults()); print(PHP_EOL); if ($out !== null) { $out->newLine(); } } } /** * "Inner" class that contains the definition of a new transaction element. * Transactions allow several files or blocks of statements * to be executed using the same JDBC connection and commit * operation in between. * * @package phing.tasks.ext.creole */ class SQLExecTransaction { private $tSrcFile = null; private $tSqlCommand = ""; private $parent; /** * @param $parent */ public function __construct($parent) { // Parent is required so that we can log things ... $this->parent = $parent; } /** * @param PhingFile $src */ public function setSrc(PhingFile $src) { $this->tSrcFile = $src; } /** * @param $sql */ public function addText($sql) { $this->tSqlCommand .= $sql; } /** * @param null $out */ public function runTransaction($out = null) { if (!empty($this->tSqlCommand)) { $this->parent->log("Executing commands", Project::MSG_INFO); $this->parent->runStatements(new StringReader($this->tSqlCommand), $out); } if ($this->tSrcFile !== null) { $this->parent->log( "Executing file: " . $this->tSrcFile->getAbsolutePath(), Project::MSG_INFO ); $reader = new FileReader($this->tSrcFile); $this->parent->runStatements($reader, $out); $reader->close(); } } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-commit * * @package phing.tasks.ext.git * @author Jonathan Creasy * @see VersionControl_Git * @since 2.4.3 */ class GitCommitTask extends GitBaseTask { /** * @var boolean */ private $allFiles = false; /** * @var string */ private $message; /** * @var FileSet[] */ private $filesets = array(); /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } if ($this->allFiles !== true && empty($this->filesets)) { throw new BuildException('"allFiles" cannot be false if no filesets are specified.'); } $options = array(); if ($this->allFiles === true) { $options['all'] = true; } $arguments = array(); if ($this->allFiles !== true) { foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($this->project); $srcFiles = $ds->getIncludedFiles(); foreach ($srcFiles as $file) { $arguments[] = $file; } } } if (!empty($this->message)) { $options['message'] = $this->message; } else { $options['allow-empty-message'] = true; } try { $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('commit'); $command->setArguments($arguments); $command->setOptions($options); $command->execute(); } catch (Exception $e) { throw new BuildException('The remote end hung up unexpectedly', $e); } $this->logCommand($options, $arguments); } /** * @param array $options * @param array $arguments */ protected function logCommand(array $options, array $arguments) { $msg = 'git-commit: Executed git commit '; foreach ($options as $option => $value) { $msg .= ' --' . $option . '=' . $value; } foreach ($arguments as $argument) { $msg .= ' ' . $argument; } $this->log($msg, Project::MSG_INFO); } /** * @return bool */ public function getAllFiles() { return $this->allFiles; } /** * @param $flag */ public function setAllFiles($flag) { $this->allFiles = (bool) $flag; } /** * @return string */ public function getMessage() { return $this->message; } /** * @param $message */ public function setMessage($message) { $this->message = $message; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-tag * * @author Evan Kaufman * @author Victor Farazdagi * @version $Id: d01c0f1426d0075ae04ff7c156452d08909e966a $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.5 */ class GitTagTask extends GitBaseTask { /** * Make unsigned, annotated tag object. See -a of git-tag * @var boolean */ private $annotate = false; /** * Make GPG-signed tag. See -s of git-tag * @var boolean */ private $sign = false; /** * Make GPG-signed tag, using given key. See -u of git-tag * @var string */ private $keySign; /** * Replace existing tag with given name. See -f of git-tag * @var boolean */ private $replace = false; /** * Delete existing tags with given names. See -d of git-tag * @var boolean */ private $delete = false; /** * Verify gpg signature of given tag names. See -v of git-tag * @var boolean */ private $verify = false; /** * List tags with names matching given pattern. See -l of git-tag * @var boolean */ private $list = false; /** * specifies how many lines from the annotation, if any, are printed * when using -l. See -n of git-tag * @var int */ private $num; /** * Only list tags containing specified commit. See --contains of git-tag * @var string */ private $contains; /** * Use given tag message. See -m of git-tag * @var string */ private $message; /** * Take tag message from given file. See -F of git-tag * @var string */ private $file; /** * argument to git-tag * @var string */ private $name; /** * argument to git-tag * @var string */ private $commit; /** * argument to git-tag * @var string */ private $object; /** * argument to git-tag * @var string */ private $pattern; /** * Property name to set with output value from git-tag * @var string */ private $outputProperty; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('tag'); $command ->setOption('a', $this->isAnnotate()) ->setOption('s', $this->isSign()) ->setOption('f', $this->isReplace()) ->setOption('d', $this->isDelete()) ->setOption('v', $this->isVerify()) ->setOption('l', $this->isList()); if (null !== $this->getKeySign()) { $command->setOption('u', $this->getKeySign()); } if (null !== $this->getMessage()) { $command->setOption('m', $this->getMessage()); } if (null !== $this->getFile()) { $command->setOption('F', $this->getFile()); } // Use 'name' arg, if relevant if (null != $this->getName() && false == $this->isList()) { $command->addArgument($this->getName()); } if (null !== $this->getKeySign() || $this->isAnnotate() || $this->isSign()) { // Require a tag message or file if (null === $this->getMessage() && null === $this->getFile()) { throw new BuildException('"message" or "file" required to make a tag'); } } // Use 'commit' or 'object' args, if relevant if (null !== $this->getCommit()) { $command->addArgument($this->getCommit()); } else { if (null !== $this->getObject()) { $command->addArgument($this->getObject()); } } // Customize list (-l) options if ($this->isList()) { if (null !== $this->getContains()) { $command->setOption('contains', $this->getContains()); } if (null !== $this->getPattern()) { $command->addArgument($this->getPattern()); } if (null != $this->getNum()) { $command->setOption('n', $this->getNum()); } } $this->log('git-tag command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { $this->log($e->getMessage(), Project::MSG_ERR); throw new BuildException('Task execution failed. ' . $e->getMessage()); } if (null !== $this->outputProperty) { $this->project->setProperty($this->outputProperty, $output); } $this->log( sprintf('git-tag: tags for "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-tag output: ' . trim($output), Project::MSG_INFO); } /** * @param $flag */ public function setAnnotate($flag) { $this->annotate = (bool) $flag; } /** * @return bool */ public function getAnnotate() { return $this->annotate; } /** * @return bool */ public function isAnnotate() { return $this->getAnnotate(); } /** * @param $flag */ public function setSign($flag) { $this->sign = (bool) $flag; } /** * @return bool */ public function getSign() { return $this->sign; } /** * @return bool */ public function isSign() { return $this->getSign(); } /** * @param $keyId */ public function setKeySign($keyId) { $this->keySign = $keyId; } /** * @return string */ public function getKeySign() { return $this->keySign; } /** * @param $flag */ public function setReplace($flag) { $this->replace = (bool) $flag; } /** * @return bool */ public function getReplace() { return $this->replace; } /** * @return bool */ public function isReplace() { return $this->getReplace(); } /** * @param $flag */ public function setForce($flag) { return $this->setReplace($flag); } /** * @param $flag */ public function setDelete($flag) { $this->delete = (bool) $flag; } /** * @return bool */ public function getDelete() { return $this->delete; } /** * @return bool */ public function isDelete() { return $this->getDelete(); } /** * @param $flag */ public function setVerify($flag) { $this->verify = (bool) $flag; } /** * @return bool */ public function getVerify() { return $this->verify; } /** * @return bool */ public function isVerify() { return $this->getVerify(); } /** * @param $flag */ public function setList($flag) { $this->list = (bool) $flag; } /** * @return bool */ public function getList() { return $this->list; } /** * @return bool */ public function isList() { return $this->getList(); } /** * @param $num */ public function setNum($num) { $this->num = (int) $num; } /** * @return int */ public function getNum() { return $this->num; } /** * @param $commit */ public function setContains($commit) { $this->contains = $commit; } /** * @return string */ public function getContains() { return $this->contains; } /** * @param $msg */ public function setMessage($msg) { $this->message = $msg; } /** * @return string */ public function getMessage() { return $this->message; } /** * @param $file */ public function setFile($file) { $this->file = $file; } /** * @return string */ public function getFile() { return $this->file; } /** * @param $name */ public function setName($name) { $this->name = $name; } /** * @return string */ public function getName() { return $this->name; } /** * @param $commit */ public function setCommit($commit) { $this->commit = $commit; } /** * @return string */ public function getCommit() { return $this->commit; } /** * @param $object */ public function setObject($object) { $this->object = $object; } /** * @return string */ public function getObject() { return $this->object; } /** * @param $pattern */ public function setPattern($pattern) { $this->pattern = $pattern; } /** * @return string */ public function getPattern() { return $this->pattern; } /** * @param $prop */ public function setOutputProperty($prop) { $this->outputProperty = $prop; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-fetch * * @author Victor Farazdagi * @version $Id: 0de7b4504804e074f617010ef52604d1da1e76b7 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitFetchTask extends GitBaseTask { /** * --force, -f key to git-fetch * @var boolean */ private $force = false; /** * --quiet, -q key to git-fetch * @var boolean */ private $quiet = false; /** * Fetch all remotes * --all key to git-fetch * @var boolean */ private $allRemotes = false; /** * Keep downloaded pack * --keep key to git-fetch * @var boolean */ private $keepFiles = false; /** * After fetching, remove any remote tracking branches which no longer * exist on the remote. * --prune key to git fetch * @var boolean */ private $prune = false; /** * Disable/enable automatic tag following * --no-tags key to git-fetch * @var boolean */ private $noTags = false; /** * Fetch all tags (even not reachable from branch heads) * --tags key to git-fetch * @var boolean */ private $tags = false; /** * argument to git-fetch * @var string */ private $group; /** * argument to git-fetch * @var string */ private $source = 'origin'; /** * argument to git-fetch * @var string */ private $refspec; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('fetch'); $command ->setOption('tags', $this->isTags()) ->setOption('no-tags', $this->isNoTags()) ->setOption('prune', $this->isPrune()) ->setOption('keep', $this->isKeepFiles()) ->setOption('q', $this->isQuiet()) ->setOption('force', $this->isForce()); // set operation target if ($this->isAllRemotes()) { // --all $command->setOption('all', true); } elseif ($this->getGroup()) { // $command->addArgument($this->getGroup()); } elseif ($this->getSource()) { // [] $command->addArgument($this->getSource()); if ($this->getRefspec()) { $command->addArgument($this->getRefspec()); } } else { throw new BuildException('No remote repository specified'); } $this->log('git-fetch command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log( sprintf('git-fetch: branch "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-fetch output: ' . trim($output), Project::MSG_INFO); } /** * @param $flag */ public function setForce($flag) { $this->force = $flag; } /** * @return bool */ public function getForce() { return $this->force; } /** * @return bool */ public function isForce() { return $this->getForce(); } /** * @param $flag */ public function setQuiet($flag) { $this->quiet = $flag; } /** * @return bool */ public function getQuiet() { return $this->quiet; } /** * @return bool */ public function isQuiet() { return $this->getQuiet(); } /** * @param $flag */ public function setAll($flag) { $this->allRemotes = $flag; } /** * @return bool */ public function getAll() { return $this->allRemotes; } /** * @return bool */ public function isAllRemotes() { return $this->getAll(); } /** * @param $flag */ public function setKeep($flag) { $this->keepFiles = $flag; } /** * @return bool */ public function getKeep() { return $this->keepFiles; } /** * @return bool */ public function isKeepFiles() { return $this->getKeep(); } /** * @param $flag */ public function setPrune($flag) { $this->prune = $flag; } /** * @return bool */ public function getPrune() { return $this->prune; } /** * @return bool */ public function isPrune() { return $this->getPrune(); } /** * @param $flag */ public function setNoTags($flag) { $this->noTags = $flag; } /** * @return bool */ public function getNoTags() { return $this->noTags; } /** * @return bool */ public function isNoTags() { return $this->getNoTags(); } /** * @param $flag */ public function setTags($flag) { $this->tags = $flag; } /** * @return bool */ public function getTags() { return $this->tags; } /** * @return bool */ public function isTags() { return $this->getTags(); } /** * @param $source */ public function setSource($source) { $this->source = $source; } /** * @return string */ public function getSource() { return $this->source; } /** * @param $spec */ public function setRefspec($spec) { $this->refspec = $spec; } /** * @return string */ public function getRefspec() { return $this->refspec; } /** * @param $group */ public function setGroup($group) { $this->group = $group; } /** * @return string */ public function getGroup() { return $this->group; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-checkout * * @author Victor Farazdagi * @version $Id: 0eb5ad0732bc3acd74df7f9256b37952ddce3212 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitCheckoutTask extends GitBaseTask { /** * Branch name * @var string */ private $branchname; /** * If not HEAD, specify starting point * @var string */ private $startPoint; /** * --force, -f key to git-checkout * @var boolean */ private $force = false; /** * --quiet, -q key to git-checkout * @var boolean */ private $quiet = false; /** * When creating a new branch, set up "upstream" configuration. * --track key to git-checkout * @var boolean */ private $track = false; /** * Do not set up "upstream" configuration * --no-track key to git-checkout * @var boolean */ private $noTrack = false; /** * -b, -B, -m options to git-checkout * Respective task options: * create, forceCreate, merge * @var array */ private $extraOptions = array( 'b' => false, 'B' => false, 'm' => false, ); /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } if (null === $this->getBranchname()) { throw new BuildException('"branchname" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('checkout'); $command ->setOption('no-track', $this->isNoTrack()) ->setOption('q', $this->isQuiet()) ->setOption('force', $this->isForce()) ->setOption('b', $this->isCreate()) ->setOption('B', $this->isForceCreate()) ->setOption('m', $this->isMerge()); if ($this->isNoTrack()) { $command->setOption('track', $this->isTrack()); } $command->addArgument($this->getBranchname()); if (null !== $this->getStartPoint()) { $command->addArgument($this->getStartPoint()); } $this->log('git-checkout command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log( sprintf('git-checkout: checkout "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-checkout output: ' . trim($output), Project::MSG_INFO); } /** * @param $branchname */ public function setBranchname($branchname) { $this->branchname = $branchname; } /** * @return string */ public function getBranchname() { return $this->branchname; } /** * @param $startPoint */ public function setStartPoint($startPoint) { $this->startPoint = $startPoint; } /** * @return string */ public function getStartPoint() { return $this->startPoint; } /** * @param $flag */ public function setForce($flag) { $this->force = $flag; } /** * @return bool */ public function getForce() { return $this->force; } /** * @return bool */ public function isForce() { return $this->getForce(); } /** * @param $flag */ public function setQuiet($flag) { $this->quiet = $flag; } /** * @return bool */ public function getQuiet() { return $this->quiet; } /** * @return bool */ public function isQuiet() { return $this->getQuiet(); } /** * @param $flag */ public function setTrack($flag) { $this->track = $flag; } /** * @return bool */ public function getTrack() { return $this->track; } /** * @return bool */ public function isTrack() { return $this->getTrack(); } /** * @param $flag */ public function setNoTrack($flag) { $this->noTrack = $flag; } /** * @return bool */ public function getNoTrack() { return $this->noTrack; } /** * @return bool */ public function isNoTrack() { return $this->getNoTrack(); } /** * @param $flag */ public function setCreate($flag) { $this->extraOptions['b'] = $flag; } public function getCreate() { return $this->extraOptions['b']; } public function isCreate() { return $this->getCreate(); } // -B flag is not found in all versions of git // --force is present everywhere /** * @param $flag */ public function setForceCreate($flag) { $this->setForce($flag); } public function getForceCreate() { return $this->extraOptions['B']; } public function isForceCreate() { return $this->getForceCreate(); } /** * @param $flag */ public function setMerge($flag) { $this->extraOptions['m'] = $flag; } public function getMerge() { return $this->extraOptions['m']; } public function isMerge() { return $this->getMerge(); } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-gc * * @author Victor Farazdagi * @version $Id: 5201d8d2dfb0c6ffb371ee85b8aa4bfc731b00c4 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitGcTask extends GitBaseTask { /** * --aggressive key to git-gc * @var boolean */ private $isAggressive = false; /** * --auto key to git-gc * @var boolean */ private $isAuto = false; /** * --no-prune key to git-gc * @var boolean */ private $noPrune = false; /** * --prune=option of git-gc * @var string */ private $prune = '2.weeks.ago'; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('gc'); $command ->setOption('aggressive', $this->isAggressive()) ->setOption('auto', $this->isAuto()) ->setOption('no-prune', $this->isNoPrune()); if ($this->isNoPrune() == false) { $command->setOption('prune', $this->getPrune()); } // suppress output $command->setOption('q'); $this->log('git-gc command: ' . $command->createCommandString(), Project::MSG_INFO); try { $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed', $e); } $this->log( sprintf('git-gc: cleaning up "%s" repository', $this->getRepository()), Project::MSG_INFO ); } /** * @see getAggressive() */ public function isAggressive() { return $this->getAggressive(); } /** * @return bool */ public function getAggressive() { return $this->isAggressive; } /** * @param $flag */ public function setAggressive($flag) { $this->isAggressive = (bool) $flag; } /** * @see getAuto() */ public function isAuto() { return $this->getAuto(); } /** * @return bool */ public function getAuto() { return $this->isAuto; } /** * @param $flag */ public function setAuto($flag) { $this->isAuto = (bool) $flag; } /** * @see NoPrune() */ public function isNoPrune() { return $this->getNoPrune(); } /** * @return bool */ public function getNoPrune() { return $this->noPrune; } /** * @param $flag */ public function setNoPrune($flag) { $this->noPrune = (bool) $flag; } /** * @return string */ public function getPrune() { return $this->prune; } /** * @param $date */ public function setPrune($date) { $this->prune = $date; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-branch * * @author Victor Farazdagi * @version $Id: 0a0ccdabd2fb96209a3f7c2b5069408502064e71 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitBranchTask extends GitBaseTask { /** * Branch name * @var string */ private $branchname; /** * New Branch name for git-branch -m | -M * @var string */ private $newbranch; /** * If not HEAD, specify starting point * @var string */ private $startPoint; /** * --set-upstream key to git-branch * @var boolean */ private $setUpstream = false; /** * --track key to git-branch * @var boolean */ private $track = false; /** * --no-track key to git-branch * @var boolean */ private $noTrack = false; /** * --force, -f key to git-branch * @var boolean */ private $force = false; /** * -d, -D, -m, -M options to git-branch * Respective task options: * delete, forceDelete, move, forceMove * @var array */ private $extraOptions = array( 'd' => false, 'D' => false, 'm' => false, 'M' => false, ); /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } if (null === $this->getBranchname()) { throw new BuildException('"branchname" is required parameter'); } // if we are moving branch, we need to know new name if ($this->isMove() || $this->isForceMove()) { if (null === $this->getNewbranch()) { throw new BuildException('"newbranch" is required parameter'); } } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('branch'); $command ->setOption('set-upstream', $this->isSetUpstream()) ->setOption('no-track', $this->isNoTrack()) ->setOption('force', $this->isForce()); if ($this->isNoTrack() == false) { $command->setOption('track', $this->getTrack()); } // check extra options (delete, move) foreach ($this->extraOptions as $option => $flag) { if ($flag) { $command->setOption($option, true); } } $command->addArgument($this->getBranchname()); if (null !== $this->getStartPoint()) { $command->addArgument($this->getStartPoint()); } if (null !== $this->getNewbranch()) { $command->addArgument($this->getNewbranch()); } $this->log('git-branch command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log( sprintf('git-branch: branch "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-branch output: ' . trim($output), Project::MSG_INFO); } /** * @param $flag */ public function setSetUpstream($flag) { $this->setUpstream = $flag; } /** * @return bool */ public function getSetUpstream() { return $this->setUpstream; } /** * @return bool */ public function isSetUpstream() { return $this->getSetUpstream(); } /** * @param $flag */ public function setTrack($flag) { $this->track = $flag; } /** * @return bool */ public function getTrack() { return $this->track; } /** * @return bool */ public function isTrack() { return $this->getTrack(); } /** * @param $flag */ public function setNoTrack($flag) { $this->noTrack = $flag; } /** * @return bool */ public function getNoTrack() { return $this->noTrack; } /** * @return bool */ public function isNoTrack() { return $this->getNoTrack(); } /** * @param $flag */ public function setForce($flag) { $this->force = $flag; } /** * @return bool */ public function getForce() { return $this->force; } /** * @return bool */ public function isForce() { return $this->getForce(); } /** * @param $branchname */ public function setBranchname($branchname) { $this->branchname = $branchname; } /** * @return string */ public function getBranchname() { return $this->branchname; } /** * @param $startPoint */ public function setStartPoint($startPoint) { $this->startPoint = $startPoint; } /** * @return string */ public function getStartPoint() { return $this->startPoint; } /** * @param $flag */ public function setDelete($flag) { $this->extraOptions['d'] = $flag; } public function getDelete() { return $this->extraOptions['d']; } public function isDelete() { return $this->getDelete(); } /** * @param $flag */ public function setForceDelete($flag) { $this->extraOptions['D'] = $flag; } public function getForceDelete() { return $this->extraOptions['D']; } /** * @param $flag */ public function setMove($flag) { $this->extraOptions['m'] = $flag; } public function getMove() { return $this->extraOptions['m']; } public function isMove() { return $this->getMove(); } /** * @param $flag */ public function setForceMove($flag) { $this->extraOptions['M'] = $flag; } public function getForceMove() { return $this->extraOptions['M']; } public function isForceMove() { return $this->getForceMove(); } /** * @param $name */ public function setNewBranch($name) { $this->newbranch = $name; } /** * @return string */ public function getNewBranch() { return $this->newbranch; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-merge * * @author Victor Farazdagi * @version $Id: e5d20b926ab512d72bfc19ac2f1ccc80d09f036c $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 * @link http://www.kernel.org/pub/software/scm/git/docs/git-merge.html */ class GitMergeTask extends GitBaseTask { /** * of git-merge * @var string */ private $remote; /** * Commit message * @var string */ private $message; /** * Merge strategy. See -s of git-merge * Available strategies are: octopus ours recursive resolve subtree * @var string */ private $strategy; /** * -X or --strategy-option of git-merge * @var string */ private $strategyOption; /** * --commit key of git-merge * @var boolean */ private $commit = false; /** * --no-commit key of git-merge * @var boolean */ private $noCommit = false; /** * --ff --no-ff keys to git-merge * @var boolean */ private $fastForwardCommit = false; /** * --quiet, -q key to git-merge * @var boolean */ private $quiet = false; /** * Valid merge strategies * @var array */ private $validStrategies = array( 'octopus', 'ours', 'theirs', 'recursive', 'resolve', 'subtree' ); /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $remotes = trim($this->getRemote()); if (null === $remotes || '' === $remotes) { throw new BuildException('"remote" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('merge'); $command ->setOption('commit', $this->isCommit()) ->setOption('q', $this->isQuiet()); if ($this->getMessage()) { $command->setOption('message', $this->getMessage()); } if (!$this->isCommit()) { $command->setOption('no-commit', $this->isNoCommit()); } if ($this->isFastForwardCommit()) { $command->setOption('no-ff', true); } $strategy = $this->getStrategy(); if ($strategy) { // check if strategy is valid if (false === in_array($strategy, $this->validStrategies)) { throw new BuildException( "Could not find merge strategy '" . $strategy . "'\n" . "Available strategies are: " . implode(', ', $this->validStrategies)); } $command->setOption('strategy', $strategy); if ($this->getStrategyOption()) { $command->setOption( 'strategy-option', $this->getStrategyOption() ); } } $remotes = explode(' ', $this->getRemote()); foreach ($remotes as $remote) { $command->addArgument($remote); } $this->log('git-merge command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log( sprintf('git-merge: replaying "%s" commits', $this->getRemote()), Project::MSG_INFO ); $this->log('git-merge output: ' . trim($output), Project::MSG_INFO); } /** * @param $remote */ public function setRemote($remote) { $this->remote = $remote; } /** * @return string */ public function getRemote() { return $this->remote; } /** * @param $message */ public function setMessage($message) { $this->message = $message; } /** * @return string */ public function getMessage() { return $this->message; } /** * @param $strategy */ public function setStrategy($strategy) { $this->strategy = $strategy; } /** * @return string */ public function getStrategy() { return $this->strategy; } /** * @param $strategyOption */ public function setStrategyOption($strategyOption) { $this->strategyOption = $strategyOption; } /** * @return string */ public function getStrategyOption() { return $this->strategyOption; } /** * @param $flag */ public function setQuiet($flag) { $this->quiet = $flag; } /** * @return bool */ public function getQuiet() { return $this->quiet; } /** * @return bool */ public function isQuiet() { return $this->getQuiet(); } /** * @param $flag */ public function setCommit($flag) { $this->commit = (boolean) $flag; } /** * @return bool */ public function getCommit() { return $this->commit; } /** * @return bool */ public function isCommit() { return $this->getCommit(); } /** * @param $flag */ public function setNoCommit($flag) { $this->noCommit = (boolean) $flag; } /** * @return bool */ public function getNoCommit() { return $this->noCommit; } /** * @return bool */ public function isNoCommit() { return $this->getNoCommit(); } /** * @param $flag */ public function setFastForwardCommit($flag) { $this->fastForwardCommit = $flag; } /** * @return bool */ public function getFastForwardCommit() { return $this->fastForwardCommit; } /** * @return bool */ public function isFastForwardCommit() { return $this->getFastForwardCommit(); } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-describe * * @package phing.tasks.ext.git * @author Siad Ardroumli * @see VersionControl_Git */ class GitDescribeTask extends GitBaseTask { /** * Use any ref found in .git/refs/. See --all of git-describe * @var boolean */ private $all = false; /** * Use any tag found in .git/refs/tags. See --tags of git-describe * @var boolean */ private $tags = false; /** * Find tag that contains the commit. See --contains of git-describe * @var boolean */ private $contains = false; /** * Use digit object name. See --abbrev of git-describe * @var integer */ private $abbrev; /** * Consider up to most recent tags. See --candidates of git-describe * @var integer */ private $candidates; /** * Always output the long format. See --long of git-describe * @var boolean */ private $long = false; /** * Only consider tags matching the given pattern. See --match of git-describe * @var string */ private $match; /** * Show uniquely abbreviated commit object as fallback. See --always of git-describe * @var boolean */ private $always = false; /** * argument to git-describe * @var string */ private $committish; /** * Property name to set with output value from git-describe * @var string */ private $outputProperty; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('describe'); $command ->setOption('all', $this->isAll()) ->setOption('tags', $this->isTags()) ->setOption('contains', $this->isContains()) ->setOption('long', $this->isLong()) ->setOption('always', $this->isAlways()); if (null !== $this->getAbbrev()) { $command->setOption('abbrev', $this->getAbbrev()); } if (null !== $this->getCandidates()) { $command->setOption('candidates', $this->getCandidates()); } if (null !== $this->getMatch()) { $command->setOption('match', $this->getMatch()); } if (null !== $this->getCommittish()) { $command->addArgument($this->getCommittish()); } try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed'); } if (null !== $this->outputProperty) { $this->project->setProperty($this->outputProperty, $output); } $this->log( sprintf('git-describe: recent tags for "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-describe output: ' . trim($output), Project::MSG_INFO); } /** * @param $flag */ public function setAll($flag) { $this->all = (bool) $flag; } /** * @return bool */ public function getAll() { return $this->all; } /** * @return bool */ public function isAll() { return $this->getAll(); } /** * @param $flag */ public function setTags($flag) { $this->tags = (bool) $flag; } /** * @return bool */ public function getTags() { return $this->tags; } /** * @return bool */ public function isTags() { return $this->getTags(); } /** * @param $flag */ public function setContains($flag) { $this->contains = (bool) $flag; } /** * @return bool */ public function getContains() { return $this->contains; } /** * @return bool */ public function isContains() { return $this->getContains(); } /** * @param $length */ public function setAbbrev($length) { $this->abbrev = (int) $length; } /** * @return int */ public function getAbbrev() { return $this->abbrev; } /** * @param $count */ public function setCandidates($count) { $this->candidates = (int) $count; } /** * @return int */ public function getCandidates() { return $this->candidates; } /** * @param $flag */ public function setLong($flag) { $this->long = (bool) $flag; } /** * @return bool */ public function getLong() { return $this->long; } /** * @return bool */ public function isLong() { return $this->getLong(); } /** * @param $pattern */ public function setMatch($pattern) { $this->match = $pattern; } /** * @return string */ public function getMatch() { return $this->match; } /** * @param $flag */ public function setAlways($flag) { $this->always = (bool) $flag; } /** * @return bool */ public function getAlways() { return $this->always; } /** * @return bool */ public function isAlways() { return $this->getAlways(); } /** * @param $object */ public function setCommittish($object) { $this->committish = $object; } /** * @return string */ public function getCommittish() { return $this->committish; } /** * @param string $prop */ public function setOutputProperty($prop) { $this->outputProperty = $prop; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-push * * @author Victor Farazdagi * @version $Id: 8406c9cfd560b995db09e9888334355641cd3975 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 * @link http://www.kernel.org/pub/software/scm/git/docs/git-push.html */ class GitPushTask extends GitBaseTask { /** * Instead of naming each ref to push, specifies that all refs * --all key to git-push * @var boolean */ private $allRemotes = false; /** * Mirror to remote repository * --mirror key to git-push * @var boolean */ private $mirror = false; /** * Same as prefixing repos with colon * --delete argument to git-push * @var string */ private $delete = false; /** * Push all refs under refs/tags * --tags key to git-fetch * @var boolean */ private $tags = false; /** * argument to git-push * @var string */ private $destination = 'origin'; /** * argument to git-push * @var string */ private $refspec; /** * --force, -f key to git-push * @var boolean */ private $force = false; /** * --quiet, -q key to git-push * @var boolean */ private $quiet = true; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('push'); $command ->setOption('tags', $this->isTags()) ->setOption('mirror', $this->isMirror()) ->setOption('delete', $this->isDelete()) ->setOption('q', $this->isQuiet()) ->setOption('force', $this->isForce()); // set operation target if ($this->isAllRemotes()) { // --all $command->setOption('all', true); $this->log('git-push: push to all refs', Project::MSG_INFO); } elseif ($this->isMirror()) { // [] $command->setOption('mirror', true); $this->log('git-push: mirror all refs', Project::MSG_INFO); } elseif ($this->getDestination()) { // [] $command->addArgument($this->getDestination()); if ($this->getRefspec()) { $command->addArgument($this->getRefspec()); } $this->log( sprintf( 'git-push: pushing to %s %s', $this->getDestination(), $this->getRefspec() ), Project::MSG_INFO ); } else { throw new BuildException('At least one destination must be provided'); } $this->log('git-push command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log('git-push: complete', Project::MSG_INFO); if ($this->isDelete()) { $this->log('git-push: branch delete requested', Project::MSG_INFO); } $this->log('git-push output: ' . trim($output), Project::MSG_INFO); } /** * @param $flag */ public function setAll($flag) { $this->allRemotes = $flag; } /** * @return bool */ public function getAll() { return $this->allRemotes; } /** * @return bool */ public function isAllRemotes() { return $this->getAll(); } /** * @param $flag */ public function setMirror($flag) { $this->mirror = (boolean) $flag; } /** * @return bool */ public function getMirror() { return $this->mirror; } /** * @return bool */ public function isMirror() { return $this->getMirror(); } /** * @param $flag */ public function setDelete($flag) { $this->delete = (boolean) $flag; } /** * @return string */ public function getDelete() { return $this->delete; } /** * @return string */ public function isDelete() { return $this->getDelete(); } /** * @param $flag */ public function setTags($flag) { $this->tags = $flag; } /** * @return bool */ public function getTags() { return $this->tags; } /** * @return bool */ public function isTags() { return $this->getTags(); } /** * @param $destination */ public function setDestination($destination) { $this->destination = $destination; } /** * @return string */ public function getDestination() { return $this->destination; } /** * @param $spec */ public function setRefspec($spec) { $this->refspec = $spec; } /** * @return string */ public function getRefspec() { return $this->refspec; } /** * @param $flag */ public function setForce($flag) { $this->force = $flag; } /** * @return bool */ public function getForce() { return $this->force; } /** * @return bool */ public function isForce() { return $this->getForce(); } /** * @param $flag */ public function setQuiet($flag) { $this->quiet = $flag; } /** * @return bool */ public function getQuiet() { return $this->quiet; } /** * @return bool */ public function isQuiet() { return $this->getQuiet(); } } . */ require_once 'phing/Task.php'; require_once 'phing/BuildException.php'; /** * Base class for Git tasks * * @author Victor Farazdagi * @version $Id: 85ccdb98750754b0376c5a367925b260788f4086 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ abstract class GitBaseTask extends Task { /** * Bath to git binary * @var string */ private $gitPath = '/usr/bin/git'; /** * @var VersionControl_Git */ private $gitClient = null; /** * Current repository directory * @var string */ private $repository; /** * Initialize Task. * Check and include necessary libraries. */ public function init() { @include_once 'VersionControl/Git.php'; if (false == class_exists('VersionControl_Git')) { throw new BuildException("The Git tasks depend on PEAR\'s " . "VersionControl_Git package.", $this->getLocation()); } } /** * Set repository directory * * @param string $repository Repo directory * @return GitBaseTask */ public function setRepository($repository) { $this->repository = $repository; return $this; } /** * Get repository directory * * @return string */ public function getRepository() { return $this->repository; } /** * Set path to git executable * * @param string $gitPath New path to git repository * @return GitBaseTask */ public function setGitPath($gitPath) { $this->gitPath = $gitPath; return $this; } /** * Get path to git executable * * @return string */ public function getGitPath() { return $this->gitPath; } /** * @param bool $reset * @param null $repository * @return null|VersionControl_Git * @throws BuildException */ protected function getGitClient($reset = false, $repository = null) { $this->gitClient = ($reset === true) ? null : $this->gitClient; $repository = (null === $repository) ? $this->getRepository() : $repository; if (null === $this->gitClient) { try { $this->gitClient = new VersionControl_Git($repository); } catch (VersionControl_Git_Exception $e) { // re-package throw new BuildException( 'You must specify readable directory as repository.', $e); } } $this->gitClient->setGitCommandPath($this->getGitPath()); return $this->gitClient; } } . */ require_once 'phing/Task.php'; require_once 'phing/BuildException.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Repository initialization task * * @author Victor Farazdagi * @version $Id: 8e8b0c6caa7260a0bb563b71f8af4291067cbef0 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitInitTask extends GitBaseTask { /** * Whether --bare key should be set for git-init * @var string */ private $isBare = false; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(); $client->initRepository($this->isBare()); $msg = 'git-init: initializing ' . ($this->isBare() ? '(bare) ' : '') . '"' . $this->getRepository() . '" repository'; $this->log($msg, Project::MSG_INFO); } /** * Alias @see getBare() * * @return string */ public function isBare() { return $this->getBare(); } /** * @return string */ public function getBare() { return $this->isBare; } /** * @param $flag */ public function setBare($flag) { $this->isBare = (bool) $flag; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper around git-clone * * @author Victor Farazdagi * @version $Id: 1ca04138e62374984bd4e04a46fccec605dff5a7 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitCloneTask extends GitBaseTask { /** * Whether --depth key should be set for git-clone * @var int */ private $depth = 0; /** * Whether --bare key should be set for git-clone * @var bool */ private $isBare = false; /** * Whether --single-branch key should be set for git-clone * @var bool */ private $singleBranch = false; /** * Branch to check out * * @var string */ private $branch = ""; /** * Path to target directory * @var string */ private $targetPath; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } if (null === $this->getTargetPath()) { throw new BuildException('"targetPath" is required parameter'); } $files = @scandir($this->getTargetPath()); if (isset($files) && is_array($files) && (count($files) > 2)) { throw new BuildException( sprintf( '"%s" target directory is not empty', $this->getTargetPath() ) ); } try { $this->doClone($this->getGitClient(false, getcwd())); } catch (Exception $e) { throw new BuildException('The remote end hung up unexpectedly', $e); } $msg = 'git-clone: cloning ' . ($this->isBare() ? '(bare) ' : '') . ($this->hasDepth() ? ' (depth="' . $this->getDepth() . '") ' : '') . '"' . $this->getRepository() . '" repository' . ' to "' . $this->getTargetPath() . '" directory'; $this->log($msg, Project::MSG_INFO); } /** * Create a new clone * * @param VersionControl_Git $client * * @throws VersionControl_Git_Exception */ protected function doClone(VersionControl_Git $client) { $command = $client->getCommand('clone') ->setOption('q') ->setOption('bare', $this->isBare()) ->setOption('single-branch', $this->isSingleBranch()) ->setOption('depth', $this->hasDepth() ? $this->getDepth() : false) ->setOption('branch', $this->hasBranch() ? $this->getBranch() : false) ->addArgument($this->getRepository()) ->addArgument($this->getTargetPath()); if (is_dir($this->getTargetPath()) && version_compare('1.6.1.4', $client->getGitVersion(), '>=')) { $isEmptyDir = true; $entries = scandir($this->getTargetPath()); foreach ($entries as $entry) { if ('.' !== $entry && '..' !== $entry) { $isEmptyDir = false; break; } } if ($isEmptyDir) { @rmdir($this->getTargetPath()); } } $command->execute(); } /** * @return int */ public function getDepth() { return $this->depth; } /** * @param int $depth */ public function setDepth($depth) { $this->depth = $depth; } /** * @return bool */ public function hasDepth() { return (bool) $this->depth; } /** * Get path to target direcotry repo * * @return string */ public function getTargetPath() { return $this->targetPath; } /** * Set path to source repo * * @param string $targetPath Path to repository used as source * @return void */ public function setTargetPath($targetPath) { $this->targetPath = $targetPath; } /** * Alias @see getBare() * * @return bool */ public function isBare() { return $this->getBare(); } /** * @return bool */ public function getBare() { return $this->isBare; } /** * @param $flag */ public function setBare($flag) { $this->isBare = (bool) $flag; } /** * @return boolean */ public function isSingleBranch() { return $this->singleBranch; } /** * @param boolean $singleBranch */ public function setSingleBranch($singleBranch) { $this->singleBranch = $singleBranch; } /** * @return string */ public function getBranch() { return $this->branch; } /** * @return bool */ public function hasBranch() { return !empty($this->branch); } /** * @param string $branch */ public function setBranch($branch) { $this->branch = $branch; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-pull * * @author Victor Farazdagi * @version $Id: 3ca88dd906a2b8b95edd6c11265984a9d57dbde5 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.3 */ class GitPullTask extends GitBaseTask { /** * argument to git-pull * @var string */ private $source = 'origin'; /** * argument to git-pull * @var string */ private $refspec; /** * --rebase key to git-pull * @var boolean */ private $rebase = false; /** * --no-rebase key to git-pull * Allow to override --rebase (if set to default true in configuration) * @var boolean */ private $noRebase = false; /** * Merge strategy. See -s of git-pull * @var string */ private $strategy; /** * -X or --strategy-option of git-pull * @var string */ private $strategyOption; /** * Fetch all remotes * --all key to git-pull * @var boolean */ private $allRemotes = false; /** * --append key to git-pull * @var boolean */ private $append = false; /** * Keep downloaded pack * --keep key to git-pull * @var boolean */ private $keepFiles = false; /** * Disable/enable automatic tag following * --no-tags key to git-pull * @var boolean */ private $noTags = false; /** * Fetch all tags (even not reachable from branch heads) * --tags key to git-pull * @var boolean */ private $tags = false; /** * --quiet, -q key to git-pull * @var boolean */ private $quiet = true; /** * --force, -f key to git-pull * @var boolean */ private $force = false; /** * Valid merge strategies * @var array */ private $validStrategies = array( 'octopus', 'ours', 'recursive', 'resolve', 'subtree' ); /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('pull'); $command ->setOption('rebase', $this->isRebase()); if (!$this->isRebase()) { $command->setOption('no-rebase', $this->isNoRebase()); } $strategy = $this->getStrategy(); if ($strategy) { // check if strategy is valid if (false === in_array($strategy, $this->validStrategies)) { throw new BuildException( "Could not find merge strategy '" . $strategy . "'\n" . "Available strategies are: " . implode(', ', $this->validStrategies)); } $command->setOption('strategy', $strategy); if ($this->getStrategyOption()) { $command->setOption( 'strategy-option', $this->getStrategyOption() ); } } // order of arguments is important $command ->setOption('tags', $this->isTags()) ->setOption('no-tags', $this->isNoTags()) ->setOption('keep', $this->isKeepFiles()) ->setOption('append', $this->isAppend()) ->setOption('q', $this->isQuiet()) ->setOption('force', $this->isForce()); // set operation target if ($this->isAllRemotes()) { // --all $command->setOption('all', true); $this->log('git-pull: fetching from all remotes', Project::MSG_INFO); } elseif ($this->getSource()) { // [] $command->addArgument($this->getSource()); if ($this->getRefspec()) { $command->addArgument($this->getRefspec()); } $this->log( sprintf( 'git-pull: pulling from %s %s', $this->getSource(), $this->getRefspec() ), Project::MSG_INFO ); } else { throw new BuildException('No source repository specified'); } $this->log('git-pull command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed.', $e); } $this->log('git-pull: complete', Project::MSG_INFO); $this->log('git-pull output: ' . trim($output), Project::MSG_INFO); } /** * @param $strategy */ public function setStrategy($strategy) { $this->strategy = $strategy; } /** * @return string */ public function getStrategy() { return $this->strategy; } /** * @param $strategyOption */ public function setStrategyOption($strategyOption) { $this->strategyOption = $strategyOption; } /** * @return string */ public function getStrategyOption() { return $this->strategyOption; } /** * @param $source */ public function setSource($source) { $this->source = $source; } /** * @return string */ public function getSource() { return $this->source; } /** * @param $spec */ public function setRefspec($spec) { $this->refspec = $spec; } /** * @return string */ public function getRefspec() { return $this->refspec; } /** * @param $flag */ public function setAll($flag) { $this->allRemotes = $flag; } /** * @return bool */ public function getAll() { return $this->allRemotes; } /** * @return bool */ public function isAllRemotes() { return $this->getAll(); } /** * @param $flag */ public function setAppend($flag) { $this->append = (boolean) $flag; } /** * @return bool */ public function getAppend() { return $this->append; } /** * @return bool */ public function isAppend() { return $this->getAppend(); } /** * @param $flag */ public function setKeep($flag) { $this->keepFiles = $flag; } /** * @return bool */ public function getKeep() { return $this->keepFiles; } /** * @return bool */ public function isKeepFiles() { return $this->getKeep(); } /** * @param $flag */ public function setNoTags($flag) { $this->noTags = $flag; } /** * @return bool */ public function getNoTags() { return $this->noTags; } /** * @return bool */ public function isNoTags() { return $this->getNoTags(); } /** * @param $flag */ public function setTags($flag) { $this->tags = $flag; } /** * @return bool */ public function getTags() { return $this->tags; } /** * @return bool */ public function isTags() { return $this->getTags(); } /** * @param $flag */ public function setQuiet($flag) { $this->quiet = $flag; } /** * @return bool */ public function getQuiet() { return $this->quiet; } /** * @return bool */ public function isQuiet() { return $this->getQuiet(); } /** * @param $flag */ public function setRebase($flag) { $this->rebase = (boolean) $flag; } /** * @return bool */ public function getRebase() { return $this->rebase; } /** * @return bool */ public function isRebase() { return $this->getRebase(); } /** * @param $flag */ public function setNoRebase($flag) { $this->noRebase = (boolean) $flag; } /** * @return bool */ public function getNoRebase() { return $this->noRebase; } /** * @return bool */ public function isNoRebase() { return $this->getNoRebase(); } /** * @param $flag */ public function setForce($flag) { $this->force = $flag; } /** * @return bool */ public function getForce() { return $this->force; } /** * @return bool */ public function isForce() { return $this->getForce(); } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/git/GitBaseTask.php'; /** * Wrapper aroung git-log * * @author Evan Kaufman * @author Victor Farazdagi * @version $Id: 8b23ec7a8c95625a37c67d7cba50df578b95b2b6 $ * @package phing.tasks.ext.git * @see VersionControl_Git * @since 2.4.5 */ class GitLogTask extends GitBaseTask { /** * Generate a diffstat. See --stat of git-log * @var string|boolean */ private $stat = false; /** * Names + status of changed files. See --name-status of git-log * @var boolean */ private $nameStatus = false; /** * Number of commits to show. See -|-n|--max-count of git-log * @var integer */ private $maxCount; /** * Don't show commits with more than one parent. See --no-merges of git-log * @var boolean */ private $noMerges = false; /** * Commit format. See --format of git-log * @var string */ private $format = 'medium'; /** * Date format. See --date of git-log * @var string */ private $date; /** * argument to git-log * @var string */ private $since; /** * argument to git-log * @var string */ private $until; /** * arguments to git-log * Accepts one or more paths delimited by PATH_SEPARATOR * @var string */ private $paths; /** * Property name to set with output value from git-log * @var string */ private $outputProperty; /** * The main entry point for the task */ public function main() { if (null === $this->getRepository()) { throw new BuildException('"repository" is required parameter'); } $client = $this->getGitClient(false, $this->getRepository()); $command = $client->getCommand('log'); $command ->setOption('stat', $this->getStat()) ->setOption('name-status', $this->isNameStatus()) ->setOption('no-merges', $this->isNoMerges()) ->setOption('format', $this->getFormat()); if (null !== $this->getMaxCount()) { $command->setOption('max-count', $this->getMaxCount()); } if (null !== $this->getDate()) { $command->setOption('date', $this->getDate()); } if (null !== $this->getSince()) { $command->setOption('since', $this->getSince()); } if (null !== $this->getUntil()) { $command->setOption('until', $this->getUntil()); } $command->addDoubleDash(true); if (null !== $this->getPaths()) { $command->addDoubleDash(false); $paths = explode(PATH_SEPARATOR, $this->getPaths()); foreach ($paths as $path) { $command->addArgument($path); } } $this->log('git-log command: ' . $command->createCommandString(), Project::MSG_INFO); try { $output = $command->execute(); } catch (Exception $e) { throw new BuildException('Task execution failed', $e); } if (null !== $this->outputProperty) { $this->project->setProperty($this->outputProperty, $output); } $this->log( sprintf('git-log: commit log for "%s" repository', $this->getRepository()), Project::MSG_INFO ); $this->log('git-log output: ' . trim($output), Project::MSG_INFO); } /** * @param $stat */ public function setStat($stat) { $this->stat = $stat; } /** * @return bool|string */ public function getStat() { return $this->stat; } /** * @param $flag */ public function setNameStatus($flag) { $this->nameStatus = (boolean) $flag; } /** * @return bool */ public function getNameStatus() { return $this->nameStatus; } /** * @return bool */ public function isNameStatus() { return $this->getNameStatus(); } /** * @param $count */ public function setMaxCount($count) { $this->maxCount = (int) $count; } /** * @return int */ public function getMaxCount() { return $this->maxCount; } /** * @param $flag */ public function setNoMerges($flag) { $this->noMerges = (bool) $flag; } /** * @return bool */ public function getNoMerges() { return $this->noMerges; } /** * @return bool */ public function isNoMerges() { return $this->getNoMerges(); } /** * @param $format */ public function setFormat($format) { $this->format = $format; } /** * @return string */ public function getFormat() { return $this->format; } /** * @param $date */ public function setDate($date) { $this->date = $date; } /** * @return string */ public function getDate() { return $this->date; } /** * @param $since */ public function setSince($since) { $this->since = $since; } /** * @return string */ public function getSince() { return $this->since; } /** * @param $after */ public function setAfter($after) { $this->setSince($after); } /** * @param $until */ public function setUntil($until) { $this->until = $until; } /** * @return string */ public function getUntil() { return $this->until; } /** * @param $before */ public function setBefore($before) { $this->setUntil($before); } /** * @param $paths */ public function setPaths($paths) { $this->paths = $paths; } /** * @return string */ public function getPaths() { return $this->paths; } /** * @param $prop */ public function setOutputProperty($prop) { $this->outputProperty = $prop; } } . */ require_once 'PhpDocumentor/phpDocumentor/Errors.inc'; /** * Phing subclass of the ErrorTracker class provided with PhpDocumentor to work around limitations in PhpDocumentor API. * * This class is necessary because PhpDocumentor does directly output errors and * warnings occurred during testing for undocumented elements to stdout. * This class is injected globally to force PhpDocumentor to use phing's logging * mechanism. * * Obviously this is far from ideal, but there's also no solution given the inflexibility of the * PhpDocumentor design. * * @author Timo A. Hummel @author felicitus * @version $Id: 33771f28a2886e13a8d3c38864d6758311c3e18d $ * @package phing.tasks.ext.phpdoc */ class PhingPhpDocumentorErrorTracker extends ErrorTracker { /** * @var object Reference to the task we're called with */ private $task; /** * Outputs a warning. This is an almost 1:1 copy from PhpDocumentor, * we're just processing the warning text and send it to phing's logger. * * @param $num integer Number of parameters * @return nothing */ public function addWarning($num) { $a = array('', '', '', ''); if (func_num_args() > 1) { for ($i = 1; $i < func_num_args(); $i++) { $a[$i - 1] = func_get_arg($i); } } $message = sprintf($GLOBALS['phpDocumentor_warning_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); $this->task->log($message, Project::MSG_WARN); } /** * Outputs an error. This is an almost 1:1 copy from PhpDocumentor, * we're just processing the error text and send it to phing's logger. * * @param $num integer Number of parameters * @return nothing */ public function addError($num) { $a = array('', '', '', ''); if (func_num_args() > 1) { for ($i = 1; $i < func_num_args(); $i++) { $a[$i - 1] = func_get_arg($i); } } $message = sprintf($GLOBALS['phpDocumentor_error_descrip'][$num], $a[0], $a[1], $a[2], $a[3]); $this->task->log($message, Project::MSG_ERR); } /** * Sets the task we're working with. This is necessary since we need to be * able to call the method "log". * * @param object $task The task we're working with * @return nothing */ public function setTask($task) { $this->task = $task; } } . */ require_once 'phing/Task.php'; /** * PhpDocumentor2 Task (http://www.phpdoc.org) * Based on the DocBlox Task * * @author Michiel Rook * @version $Id: fff99666d63c88940f9b305c2822856fa00ab5ce $ * @since 2.4.10 * @package phing.tasks.ext.phpdoc */ class PhpDocumentor2Task extends Task { /** * List of filesets * @var FileSet[] */ private $filesets = array(); /** * Destination/target directory * @var PhingFile */ private $destDir = null; /** * name of the template to use * @var string */ private $template = "responsive-twig"; /** * Title of the project * @var string */ private $title = "API Documentation"; /** * Name of default package * @var string */ private $defaultPackageName = "Default"; /** * Path to the phpDocumentor .phar * @var string */ private $pharLocation = ''; /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * Sets destination/target directory * @param PhingFile $destDir */ public function setDestDir(PhingFile $destDir) { $this->destDir = $destDir; } /** * Convenience setter (@see setDestDir) * @param PhingFile $output */ public function setOutput(PhingFile $output) { $this->destDir = $output; } /** * Sets the template to use * @param strings $template */ public function setTemplate($template) { $this->template = (string) $template; } /** * Sets the title of the project * @param strings $title */ public function setTitle($title) { $this->title = (string) $title; } /** * Sets the default package name * @param string $defaultPackageName */ public function setDefaultPackageName($defaultPackageName) { $this->defaultPackageName = (string) $defaultPackageName; } /** * @param string $pharLocation */ public function setPharLocation($pharLocation) { $this->pharLocation = $pharLocation; } /** * Forces phpDocumentor to be quiet * @deprecated * @param boolean $quiet */ public function setQuiet($quiet) { $this->project->log(__CLASS__ . ": the 'quiet' option has been deprecated", Project::MSG_WARN); } /** * Task entry point * @see Task::main() */ public function main() { if (empty($this->destDir)) { throw new BuildException("You must supply the 'destdir' attribute", $this->getLocation()); } if (empty($this->filesets)) { throw new BuildException("You have not specified any files to include ()", $this->getLocation()); } if (version_compare(PHP_VERSION, '5.3.0') < 0) { throw new BuildException("The phpdocumentor2 task requires PHP 5.3+"); } require_once 'phing/tasks/ext/phpdoc/PhpDocumentor2Wrapper.php'; $wrapper = new PhpDocumentor2Wrapper(); $wrapper->setProject($this->project); $wrapper->setFilesets($this->filesets); $wrapper->setDestDir($this->destDir); $wrapper->setTemplate($this->template); $wrapper->setTitle($this->title); $wrapper->setDefaultPackageName($this->defaultPackageName); $wrapper->setPharLocation($this->pharLocation); $wrapper->run(); } } . */ /** * Wrapper around PhpDocumentor2 (so we retain * PHP 5.2 compatibility in the main task) * * @author Michiel Rook * @version $Id: 9f22f2863b649ddf3820399fd5738c58900b3a24 $ * @since 2.4.10 * @package phing.tasks.ext.phpdoc */ class PhpDocumentor2Wrapper { /** * Phing project instance * @var Project */ private $project = null; /** * List of filesets * @var FileSet[] */ private $filesets = array(); /** * Destination/target directory * @var PhingFile */ private $destDir = null; /** * name of the template to use * @var string */ private $template = "responsive-twig"; /** * Title of the project * @var string */ private $title = "API Documentation"; /** * Name of the default package * @var string */ private $defaultPackageName = "Default"; /** * Path to the phpDocumentor 2 source * @var string */ private $phpDocumentorPath = ""; /** * Path to the phpDocumentor .phar * @var string */ private $pharLocation = ''; /** * @var \phpDocumentor\Application */ private $app = null; /** * Sets project instance * * @param Project $project */ public function setProject($project) { $this->project = $project; } /** * Sets filesets array * * @param FileSet[] $filesets */ public function setFilesets($filesets) { $this->filesets = $filesets; } /** * Sets destination/target directory * @param PhingFile $destDir */ public function setDestDir(PhingFile $destDir) { $this->destDir = $destDir; } /** * Sets the template to use * @param string $template */ public function setTemplate($template) { $this->template = (string) $template; } /** * Sets the title of the project * @param string $title */ public function setTitle($title) { $this->title = (string) $title; } /** * Sets the default package name * @param string $defaultPackageName */ public function setDefaultPackageName($defaultPackageName) { $this->defaultPackageName = (string) $defaultPackageName; } /** * @param string $pharLocation */ public function setPharLocation($pharLocation) { $this->pharLocation = $pharLocation; } /** * Finds and initializes the phpDocumentor installation */ private function initializePhpDocumentor() { $phpDocumentorPath = ''; if (!empty($this->pharLocation)) { include_once 'phar://' . $this->pharLocation . '/vendor/autoload.php'; if (!class_exists('phpDocumentor\\Bootstrap')) { throw new BuildException( $this->pharLocation . ' does not look like a phpDocumentor 2 .phar' ); } } elseif (class_exists('Composer\\Autoload\\ClassLoader', false)) { if (!class_exists('phpDocumentor\\Bootstrap')) { throw new BuildException('You need to install phpDocumentor 2 or add your include path to your composer installation.'); } } else { $phpDocumentorPath = $this->findPhpDocumentorPath(); if (empty($phpDocumentorPath)) { throw new BuildException("Please make sure phpDocumentor 2 is installed and on the include_path."); } set_include_path($phpDocumentorPath . PATH_SEPARATOR . get_include_path()); require_once $phpDocumentorPath . '/phpDocumentor/Bootstrap.php'; } $this->app = \phpDocumentor\Bootstrap::createInstance()->initialize(); $this->phpDocumentorPath = $phpDocumentorPath; } /** * Build a list of files (from the fileset elements) * and call the phpDocumentor parser * * @return string */ private function parseFiles() { $parser = $this->app['parser']; $builder = $this->app['descriptor.builder']; $builder->createProjectDescriptor(); $projectDescriptor = $builder->getProjectDescriptor(); $projectDescriptor->setName($this->title); $paths = array(); // filesets foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($this->project); $dir = $fs->getDir($this->project); $srcFiles = $ds->getIncludedFiles(); foreach ($srcFiles as $file) { $paths[] = $dir . FileSystem::getFileSystem()->getSeparator() . $file; } } $this->project->log("Will parse " . count($paths) . " file(s)", Project::MSG_VERBOSE); $files = new \phpDocumentor\Fileset\Collection(); $files->addFiles($paths); $mapper = new \phpDocumentor\Descriptor\Cache\ProjectDescriptorMapper($this->app['descriptor.cache']); $mapper->garbageCollect($files); $mapper->populate($projectDescriptor); $parser->setPath($files->getProjectRoot()); $parser->setDefaultPackageName($this->defaultPackageName); $parser->parse($builder, $files); $mapper->save($projectDescriptor); return $mapper; } /** * Transforms the parsed files */ private function transformFiles() { $transformer = $this->app['transformer']; $compiler = $this->app['compiler']; $builder = $this->app['descriptor.builder']; $projectDescriptor = $builder->getProjectDescriptor(); $transformer->getTemplates()->load($this->template, $transformer); $transformer->setTarget($this->destDir->getAbsolutePath()); foreach ($compiler as $pass) { $pass->execute($projectDescriptor); } } /** * Runs phpDocumentor 2 */ public function run() { $this->initializePhpDocumentor(); $cache = $this->app['descriptor.cache']; $cache->getOptions()->setCacheDir($this->destDir->getAbsolutePath()); $this->parseFiles(); $this->project->log("Transforming...", Project::MSG_VERBOSE); $this->transformFiles(); } /** * Find the correct php documentor path * * @return null|string */ private function findPhpDocumentorPath() { $phpDocumentorPath = null; $directories = array('phpDocumentor', 'phpdocumentor'); foreach ($directories as $directory) { foreach (Phing::explodeIncludePath() as $path) { $testPhpDocumentorPath = $path . DIRECTORY_SEPARATOR . $directory . DIRECTORY_SEPARATOR . 'src'; if (file_exists($testPhpDocumentorPath)) { $phpDocumentorPath = $testPhpDocumentorPath; } } } return $phpDocumentorPath; } } . */ require_once 'PhpDocumentor/phpDocumentor/Setup.inc.php'; /** * Phing subclass of the phpDocumentor_setup class provided with PhpDocumentor to work around limitations in PhpDocumentor API. * * This class is necessary because phpDocumentor_setup does not expose a complete API for setting configuration options. Because * this class must directly modify some "private" GLOBAL(!) configuration variables, it is liable to break if the PhpDocumentor * internal implementation changes. Obviously this is far from ideal, but there's also no solution given the inflexibility of the * PhpDocumentor design. * * @author Hans Lellelid @author hans * @version $Id: 3c0527274eb0d0c2c6ed888ff23fe5b38367bb04 $ * @package phing.tasks.ext.phpdoc */ class PhingPhpDocumentorSetup extends phpDocumentor_setup { /** * Constructs a new PhingPhpDocumentorSetup. * * @param null $configdir * @param object $task The task we're working with, so we can pass it on to the ErrorTracker * @internal param string $configDir Directory in which to look for configuration files. */ public function __construct($configdir = null, $task) { global $_phpDocumentor_cvsphpfile_exts, $_phpDocumentor_setting, $_phpDocumentor_phpfile_exts; $this->setup = new Io(); $this->render = new phpDocumentor_IntermediateParser("Default Title"); $GLOBALS['_phpDocumentor_install_dir'] = $configdir; $this->parseIni(); // These redundant-looking lines seem to actually make a difference. // See: http://phing.info/trac/ticket/150 $_phpDocumentor_phpfile_exts = $GLOBALS['_phpDocumentor_phpfile_exts']; $_phpDocumentor_cvsphpfile_exts = $GLOBALS['_phpDocumentor_cvsphpfile_exts']; if (tokenizer_ext) { $this->parse = new phpDocumentorTParser(); } else { $this->parse = new Parser(); } $this->setMemoryLimit(); include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorErrorTracker.php'; // Inject our own error tracker to PhpDocumentor $GLOBALS['phpDocumentor_errors'] = new PhingPhpDocumentorErrorTracker(); $GLOBALS['phpDocumentor_errors']->setTask($task); } /** * Set whether to generate sourcecode for each file parsed. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param bool $b */ public function setGenerateSourcecode($b) { global $_phpDocumentor_setting; $_phpDocumentor_setting['sourcecode'] = (boolean) $b; } /** * Set an array of README/INSTALL/CHANGELOG file paths. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param array $files Absolute paths to files. */ public function setRicFiles($files) { global $_phpDocumentor_RIC_files; $_phpDocumentor_RIC_files = $files; } /** * Set comma-separated list of tags to ignore. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param string $tags */ public function setIgnoreTags($tags) { global $_phpDocumentor_setting; $ignoretags = explode(',', $tags); $ignoretags = array_map('trim', $ignoretags); $tags = array(); foreach ($ignoretags as $tag) { if (!in_array( $tag, array('@global', '@access', '@package', '@ignore', '@name', '@param', '@return', '@staticvar', '@var') ) ) { $tags[] = $tag; } } $_phpDocumentor_setting['ignoretags'] = $tags; } /** * Set whether to parse dirs as PEAR repos. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param bool $b */ public function setPear($b) { global $_phpDocumentor_setting; $_phpDocumentor_setting['pear'] = (boolean) $b; } /** * Set fullpath to directory to look in for examples. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param string $dir */ public function setExamplesDir($dir) { global $_phpDocumentor_setting; $_phpDocumentor_setting['examplesdir'] = $dir; } /** * Sets the default package name. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param string $name */ public function setDefaultPackageName($name) { $GLOBALS['phpDocumentor_DefaultPackageName'] = trim($name); } /** * Sets the default category name. * * This method exists as a hack because there is no API exposed for this in PhpDocumentor. * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * * @param string $name */ public function setDefaultCategoryName($name) { $GLOBALS['phpDocumentor_DefaultCategoryName'] = trim($name); } /** * Enables quiet mode. * * This method exists as a hack because the API exposed for this method in PhpDocumentor * doesn't work correctly. * * Note that because we are setting a "private" GLOBAL(!!) config var with this value, this * is subject to break if PhpDocumentor internals changes. * */ public function setQuietMode() { global $_phpDocumentor_setting; $_phpDocumentor_setting['quiet'] = true; parent::setQuietMode(); } /** * Control whether or not warnings will be shown for undocumented elements. * Useful for identifying classes and methods that haven't yet been * documented. * * @param bool $bEnable */ public function setUndocumentedelements($bEnable) { $this->render->setUndocumentedElementWarningsMode($bEnable); } /** * custom tags, will be recognized and put in tags[] instead of * unknowntags[] * * This method exists as a hack because the API exposed for this method in * PhpDocumentor doesn't work correctly. * * Note that because we are setting a "private" GLOBAL(!!) config var with * this value, this is subject to break if PhpDocumentor internals changes. * * @param string $sCustomtags */ public function setCustomtags($sCustomtags) { global $_phpDocumentor_setting; $_phpDocumentor_setting['customtags'] = $sCustomtags; } /** * Files to ignore * * @param string $sIgnore */ public function setIgnore($sIgnore) { global $_phpDocumentor_setting; $_phpDocumentor_setting['ignore'] = $sIgnore; } } . */ require_once 'phing/Task.php'; /** * Task to run PhpDocumentor. * * @author Hans Lellelid * @author Michiel Rook * @version $Id: 11e97cff8a9f2331750049c1c8fe4fb57f3cc962 $ * @package phing.tasks.ext.phpdoc */ class PhpDocumentorTask extends Task { /** * @var string Title for browser window / package index. */ protected $title; /** * @var PhingFile The target directory for output files. */ protected $destdir; /** * @var array FileSet[] Filesets for files to parse. */ protected $filesets = array(); /** * @var array FileSet[] Project documentation (README/INSTALL/CHANGELOG) files. */ protected $projDocFilesets = array(); /** * @var string Package output format. */ protected $output; /** * @var boolean Whether to generate sourcecode for each file parsed. */ protected $linksource = false; /** * @var boolean Whether to parse private members. */ protected $parsePrivate = false; /** * @var boolean Whether to use javadoc descriptions (more primitive). */ protected $javadocDesc = false; /** * @var PhingFile Base directory for locating template files. */ protected $templateBase; /** * @var boolean Wheter to suppress output. */ protected $quiet = false; /** * @var string Comma-separated list of packages to output. */ protected $packages; /** * @var string Comma-separated list of tags to ignore. */ protected $ignoreTags; /** * @var string Default package name. */ protected $defaultPackageName; /** * @var string Default category name. */ protected $defaultCategoryName; /** * @var PhingFile Directory in which to look for examples. */ protected $examplesDir; /** * @var PhingFile Directory in which to look for configuration files. */ protected $configDir; /** * @var boolean Whether to parse as a PEAR repository. */ protected $pear = false; /** * @var boolean Control whether or not warnings will be shown for * undocumented elements. Useful for identifying classes and * methods that haven't yet been documented. */ protected $undocumentedelements = false; /** * @var string custom tags, will be recognized and put in tags[] instead of * unknowntags[]. */ protected $customtags = ''; /** * @var string files to ignore */ protected $ignore = ''; /** * Set the title for the generated documentation * @param $title */ public function setTitle($title) { $this->title = $title; } /** * Set the destination directory for the generated documentation * @param PhingFile $destdir */ public function setDestdir(PhingFile $destdir) { $this->destdir = $destdir; } /** * Alias for {@link setDestdir()}. * @see setDestdir() * @param PhingFile $destdir */ public function setTarget(PhingFile $destdir) { $this->setDestdir($destdir); } /** * Set the output format (e.g. HTML:Smarty:PHP). * @param string $output */ public function setOutput($output) { $this->output = $output; } /** * Set whether to generate sourcecode for each file parsed * @param boolean */ public function setSourcecode($b) { $this->setLinksource($b); } /** * Set whether to generate sourcecode for each file parsed * @param boolean */ public function setLinksource($b) { $this->linksource = $b; } /** * Set whether to suppress output. * @param boolean $b */ public function setQuiet($b) { $this->quiet = $b; } /** * Should private members/classes be documented * @param boolean */ public function setParseprivate($parseprivate) { $this->parsePrivate = $parseprivate; } /** * Whether to use javadoc descriptions (more primitive). * @param boolean */ public function setJavadocdesc($javadoc) { $this->javadocDesc = $javadoc; } /** * Set (comma-separated) list of packages to output. * * @param string $packages */ public function setPackageoutput($packages) { $this->packages = $packages; } /** * Set (comma-separated) list of tags to ignore. * * @param string $tags */ public function setIgnoretags($tags) { $this->ignoreTags = $tags; } /** * Set a directory to search for examples in. * @param PhingFile $d */ public function setExamplesdir(PhingFile $d) { $this->examplesDir = $d; } /** * Set a directory to search for configuration files in. * @param PhingFile $d */ public function setConfigdir(PhingFile $d) { $this->configDir = $d; } /** * Sets the default package name. * @param string $name */ public function setDefaultpackagename($name) { $this->defaultPackageName = $name; } /** * Sets the default category name. * @param string $name */ public function setDefaultcategoryname($name) { $this->defaultCategoryName = $name; } /** * Set whether to parse as PEAR repository. * @param boolean $b */ public function setPear($b) { $this->pear = $b; } /** * Creates a FileSet. * @return FileSet */ public function createFileset() { $num = array_push($this->filesets, new FileSet()); return $this->filesets[$num - 1]; } /** * Creates a readme/install/changelog fileset. * @return FileSet */ public function createProjdocfileset() { $num = array_push($this->projDocFilesets, new FileSet()); return $this->projDocFilesets[$num - 1]; } /** * Control whether or not warnings will be shown for undocumented elements. * Useful for identifying classes and methods that haven't yet been * documented. * @param boolean $b */ public function setUndocumentedelements($b) { $this->undocumentedelements = $b; } /** * custom tags, will be recognized and put in tags[] instead of * unknowntags[]. * * @param string $sCustomtags */ public function setCustomtags($sCustomtags) { $this->customtags = $sCustomtags; } /** * Set base location of all templates for this parse. * * @param PhingFile $oTemplateBase * @internal param PhingFile $destdir */ public function setTemplateBase(PhingFile $oTemplateBase) { $this->templateBase = $oTemplateBase; } /** * Set files to ignore * @param string $sIgnore */ public function setIgnore($sIgnore) { $this->ignore = $sIgnore; } /** * Searches include_path for PhpDocumentor install and adjusts include_path appropriately. * @throws BuildException - if unable to find PhpDocumentor on include_path */ protected function findPhpDocumentorInstall() { $found = null; foreach (Phing::explodeIncludePath() as $path) { $testpath = $path . DIRECTORY_SEPARATOR . 'PhpDocumentor'; if (file_exists($testpath)) { $found = $testpath; break; } } if (!$found) { throw new BuildException("PhpDocumentor task depends on PhpDocumentor being installed and on include_path.", $this->getLocation( )); } // otherwise, adjust the include_path to path to include the PhpDocumentor directory ... set_include_path(get_include_path() . PATH_SEPARATOR . $found); include_once "phpDocumentor/Setup.inc.php"; if (!class_exists('phpDocumentor_setup')) { throw new BuildException("Error including PhpDocumentor setup class file."); } } /** * Main entrypoint of the task * Loads the necessary environment for running PhpDoc, then runs PhpDoc * * @throws BuildException - if the phpdoc classes can't be loaded. */ public function main() { $this->findPhpDocumentorInstall(); include_once 'phing/tasks/ext/phpdoc/PhingPhpDocumentorSetup.php'; $this->validate(); $configdir = $this->configDir ? $this->configDir->getAbsolutePath() : null; $phpdoc = new PhingPhpDocumentorSetup($configdir, $this); $this->setPhpDocumentorOptions($phpdoc); //$phpdoc->readCommandLineSettings(); $phpdoc->setupConverters($this->output); $phpdoc->createDocs(); } /** * Validates that necessary minimum options have been set. * @throws BuildException if validation doesn't pass */ protected function validate() { if (!$this->destdir) { throw new BuildException("You must specify a destdir for phpdoc.", $this->getLocation()); } if (!$this->output) { throw new BuildException("You must specify an output format for phpdoc (e.g. HTML:frames:default).", $this->getLocation( )); } if (empty($this->filesets)) { throw new BuildException("You have not specified any files to include () for phpdoc.", $this->getLocation( )); } } /** * Sets the options on the passed-in phpdoc setup object. * @param PhingPhpDocumentorSetup $phpdoc */ protected function setPhpDocumentorOptions(PhingPhpDocumentorSetup $phpdoc) { // Title MUST be set first ... (because it re-initializes the internal state of the PhpDocu renderer) if ($this->title) { $phpdoc->setTitle($this->title); } if ($this->parsePrivate) { $phpdoc->setParsePrivate(); } if ($this->javadocDesc) { $phpdoc->setJavadocDesc(); } if ($this->quiet) { $phpdoc->setQuietMode(); } if ($this->destdir) { $phpdoc->setTargetDir($this->destdir->getAbsolutePath()); } if ($this->packages) { $phpdoc->setPackageOutput($this->packages); } if ($this->templateBase) { $phpdoc->setTemplateBase($this->templateBase->getAbsolutePath()); } if ($this->linksource) { $phpdoc->setGenerateSourcecode($this->linksource); } if ($this->examplesDir) { $phpdoc->setExamplesDir($this->examplesDir->getAbsolutePath()); } if ($this->ignoreTags) { $phpdoc->setIgnoreTags($this->ignoreTags); } if ($this->defaultPackageName) { $phpdoc->setDefaultPackageName($this->defaultPackageName); } if ($this->defaultCategoryName) { $phpdoc->setDefaultCategoryName($this->defaultCategoryName); } if ($this->pear) { $phpdoc->setPear($this->pear); } if ($this->ignore) { $phpdoc->setIgnore($this->ignore); } // append any files in filesets $filesToParse = array(); foreach ($this->filesets as $fs) { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); foreach ($files as $filename) { $f = new PhingFile($fs->getDir($this->project), $filename); $filesToParse[] = $f->getAbsolutePath(); } } //print_r(implode(",", $filesToParse)); $phpdoc->setFilesToParse(implode(",", $filesToParse)); // append any files in filesets $ricFiles = array(); foreach ($this->projDocFilesets as $fs) { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); foreach ($files as $filename) { $f = new PhingFile($fs->getDir($this->project), $filename); $ricFiles[] = $f->getName(); } } $phpdoc->setRicFiles($ricFiles); if ($this->undocumentedelements) { $phpdoc->setUndocumentedelements($this->undocumentedelements); } if ($this->customtags) { $phpdoc->setCustomtags($this->customtags); } } } . */ require_once 'phing/tasks/ext/phpdoc/PhpDocumentorTask.php'; /** * Task to run phpDocumentor with an external process * * This classes uses the commandline phpdoc script to build documentation. * Use this task instead of the PhpDocumentorTask when you've a clash with the * Smarty libraries. * * @author Michiel Rook * @author Markus Fischer * @version $Id: b72762694ae5d5619ecebf9b66c08bd6ff868821 $ * @package phing.tasks.ext.phpdoc */ class PhpDocumentorExternalTask extends PhpDocumentorTask { /** * The path to the executable for phpDocumentor */ protected $programPath = 'phpdoc'; protected $sourcepath = null; /** * @var bool ignore symlinks to other files or directories */ protected $ignoresymlinks = false; /** * Sets the path to the phpDocumentor executable * @param $programPath */ public function setProgramPath($programPath) { $this->programPath = $programPath; } /** * Returns the path to the phpDocumentor executable */ public function getProgramPath() { return $this->programPath; } /** * Set the source path. A directory or a comma separate list of directories. * @param $sourcepath */ public function setSourcepath($sourcepath) { $this->sourcepath = $sourcepath; } /** * Ignore symlinks to other files or directories. * * @param bool $bSet */ public function setIgnoresymlinks($bSet) { $this->ignoresymlinks = $bSet; } /** * Main entrypoint of the task */ public function main() { $this->validate(); $arguments = join(' ', $this->constructArguments()); $this->log("Running phpDocumentor..."); exec($this->programPath . " " . $arguments, $output, $return); if ($return != 0) { throw new BuildException("Could not execute phpDocumentor: " . implode(' ', $output)); } foreach ($output as $line) { if (strpos($line, 'ERROR') !== false) { $this->log($line, Project::MSG_ERR); continue; } $this->log($line, Project::MSG_VERBOSE); } } /** * Constructs an argument string for phpDocumentor * @return array */ protected function constructArguments() { $aArgs = array(); if ($this->title) { $aArgs[] = '--title "' . $this->title . '"'; } if ($this->destdir) { $aArgs[] = '--target "' . $this->destdir->getAbsolutePath() . '"'; } if ($this->sourcepath) { $aArgs[] = '--directory "' . $this->sourcepath . '"'; } if ($this->output) { $aArgs[] = '--output ' . $this->output; } if ($this->linksource) { $aArgs[] = '--sourcecode on'; } if ($this->parseprivate) { $aArgs[] = '--parseprivate on'; } if ($this->ignore) { $aArgs[] = '--ignore ' . $this->ignore; } // append any files in filesets $filesToParse = array(); foreach ($this->filesets as $fs) { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); foreach ($files as $filename) { $f = new PhingFile($fs->getDir($this->project), $filename); $filesToParse[] = $f->getAbsolutePath(); } } if (count($filesToParse) > 0) { $aArgs[] = '--filename "' . join(',', $filesToParse) . '"'; } // append any files in filesets $ricFiles = array(); foreach ($this->projDocFilesets as $fs) { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); foreach ($files as $filename) { $f = new PhingFile($fs->getDir($this->project), $filename); $ricFiles[] = $f->getAbsolutePath(); } } if (count($ricFiles) > 0) { $aArgs[] = '--readmeinstallchangelog "' . join(',', $ricFiles) . '"'; } if ($this->javadocDesc) { $aArgs[] = '--javadocdesc on'; } if ($this->quiet) { $aArgs[] = '--quiet on'; } if ($this->packages) { $aArgs[] = '--packageoutput "' . $this->packages . '"'; } if ($this->ignoreTags) { $aArgs[] = '--ignore-tags "' . $this->ignoreTags . '"'; } if ($this->defaultCategoryName) { $aArgs[] = '--defaultcategoryname "' . $this->defaultCategoryName . '"'; } if ($this->examplesDir) { $aArgs[] = '--examplesdir "' . $this->examplesDir->getAbsolutePath() . '"'; } if ($this->templateBase) { $aArgs[] = '--templatebase "' . $this->templateBase->getAbsolutePath() . '"'; } if ($this->pear) { $aArgs[] = '--pear on'; } if ($this->undocumentedelements) { $aArgs[] = '--undocumentedelements on'; } if ($this->customtags) { $aArgs[] = '--customtags "' . $this->customtags . '"'; } if ($this->ignoresymlinks) { $aArgs[] = '--ignoresymlinks on'; } return $aArgs; } /** * Override PhpDocumentorTask::init() because they're specific to the phpdoc * API which we don't use. */ public function init() { } /** * Validates that necessary minimum options have been set. Based on * PhpDocumentorTask::validate(). */ protected function validate() { if (!$this->destdir) { throw new BuildException("You must specify a destdir for phpdoc.", $this->getLocation()); } if (!$this->output) { throw new BuildException("You must specify an output format for " . "phpdoc (e.g. HTML:frames:default).", $this->getLocation()); } if (empty($this->filesets) && !$this->sourcepath) { throw new BuildException("You have not specified any files to " . "include ( or sourcepath attribute) for phpdoc.", $this->getLocation()); } if ($this->configdir) { $this->log( 'Ignoring unsupported configdir-Attribute', Project::MSG_VERBOSE ); } } } ; * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ /** * Class for collecting details for removing keys or sections from an ini file * * @category Tasks * @package phing.tasks.ext * @author Ken Guest * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ class IniFileRemove { /** * Property * * @var string */ protected $property = null; /** * Section * * @var string */ protected $section = null; /** * Set Section name * * @param string $section Name of section in ini file * * @return void */ public function setSection($section) { $this->section = $section; } /** * Set Property/Key name * * @param string $property ini key name * * @return void */ public function setProperty($property) { $this->property = $property; } /** * Get Property * * @return string */ public function getProperty() { return $this->property; } /** * Get Section * * @return string */ public function getSection() { return $this->section; } } * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ require_once 'IniFileSet.php'; require_once 'IniFileRemove.php'; require_once 'IniFileConfig.php'; /** * InifileTask * * @category Tasks * @package phing.tasks.ext * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link InifileTask.php */ class InifileTask extends Task { /** * Source file * * @var string|null */ protected $source = null; /** * Dest file * * @var string|null */ protected $dest = null; /** * Whether to halt phing on error. * * @var bool */ protected $haltonerror = false; /** * Sets * * @var array */ protected $sets = array(); /** * Removals * * @var array */ protected $removals = array(); /** * IniFileConfig instance * * @var IniFileConfig */ protected $ini = null; /** * Taskname for logger * @var string */ protected $taskName = 'IniFile'; /** * Check file to be read from * * @param string $readFile Filename * * @return void */ public function checkReadFile($readFile) { if (is_null($readFile)) { return false; } if (!file_exists($readFile)) { $msg = "$readFile does not exist."; if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); return false; } if (!is_readable($readFile)) { $msg = "$readFile is not readable."; if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); return false; } $this->ini->read($readFile); $this->log("Read from $readFile"); return true; } /** * Check file to write to * * @param string $writeFile Filename * * @return void */ public function checkWriteFile($writeFile) { if (file_exists($writeFile) && !is_writable($writeFile)) { $msg = "$writeFile is not writable"; if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); return false; } return true; } /** * The main entry point method. * * @return void */ public function main() { $this->ini = new IniFileConfig(); $readFile = null; $writeFile = null; if (!is_null($this->source) && is_null($this->dest)) { $readFile = $this->source; } elseif (!is_null($this->dest) && is_null($this->source)) { $readFile = $this->dest; } else { $readFile = $this->source; } if (!is_null($this->dest)) { $writeFile = $this->dest; } elseif (!is_null($this->source)) { $writeFile = $this->source; } else { $writeFile = $this->dest; } if ($readFile === null && $writeFile === null) { $msg = "Neither source nor dest is set"; if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); return; } if (!$this->checkReadFile($readFile)) { return; } if (!$this->checkWriteFile($writeFile)) { return; } $this->enumerateSets(); $this->enumerateRemoves(); try { $this->ini->write($writeFile); $this->log("Wrote to $writeFile"); } catch (Exception $ex) { $msg = $ex->getMessage(); if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); } } /** * Work through all Set commands. * * @return void */ public function enumerateSets() { foreach ($this->sets as $set) { $value = $set->getValue(); $key = $set->getProperty(); $section = $set->getSection(); $operation = $set->getOperation(); if ($value !== null) { try { $this->ini->set($section, $key, $value); $this->log( "[$section] $key set to $value", Project::MSG_DEBUG ); } catch (Exception $ex) { $this->log( "Error setting value for section '" . $section . "', key '" . $key ."'" ); $this->log($ex->getMessage(), Project::MSG_DEBUG); } } elseif ($operation !== null) { $v = $this->ini->get($section, $key); // value might be wrapped in quotes with a semicolon at the end if (!is_numeric($v)) { if (preg_match('/^"(\d*)";?$/', $v, $match)) { $v = $match[1]; } elseif (preg_match("/^'(\d*)';?$/", $v, $match)) { $v = $match[1]; } else { $this->log( "Value $v is not numeric. Skipping $operation operation." ); continue; } } if ($operation == '+') { ++$v; } elseif ($operation == '-') { --$v; } else { if (($operation != '-') && ($operation != '+')) { $msg = "Unrecognised operation $operation"; if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); } } try { $this->ini->set($section, $key, $v); $this->log( "[$section] $key set to $v", Project::MSG_DEBUG ); } catch (Exception $ex) { $this->log( "Error setting value for section '" . $section . "', key '" . $key ."'" ); $this->log($ex->getMessage(), Project::MSG_DEBUG); } } else { $this->log( "Set: value and operation are both not set", Project::MSG_ERR ); } } } /** * Work through all Remove commands. * * @return void */ public function enumerateRemoves() { foreach ($this->removals as $remove) { $key = $remove->getProperty(); $section = $remove->getSection(); if ($section == '') { $this->log( "Remove: section must be set", Project::MSG_ERR ); continue; } $this->ini->remove($section, $key); if (($section != '') && ($key != '')) { $this->log( "$key in section [$section] has been removed.", Project::MSG_DEBUG ); } elseif (($section != '') && ($key == '')) { $this->log("[$section] has been removed.", Project::MSG_DEBUG); } } } /** * Set Source property * * @param string $source Name of originating ini file to parse * * @return void */ public function setSource($source) { $this->source = $source; } /** * Set Dest property * * @param string $dest Destination filename to write ini contents to. * * @return void */ public function setDest($dest) { $this->dest = $dest; } /** * Set haltonerror attribute. * * @param string $halt 'yes', or '1' to halt. * * @return void */ public function setHaltonerror($halt) { $doHalt = false; if (strtolower($halt) == 'yes' || $halt == 1) { $doHalt = true; } $this->haltonerror = $doHalt; } /** * Create a Set method * * @return IniFileSet */ public function createSet() { $set = new IniFileSet(); $this->sets[] = $set; return $set; } /** * Create a Remove method * * @return IniFileRemove */ public function createRemove() { $remove = new IniFileRemove(); $this->removals[] = $remove; return $remove; } } * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ /** * InifileSet * * @category Tasks * @package phing.tasks.ext * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link InifileSet.php */ class IniFileSet { /** * Property * * @var string */ protected $property = null; /** * Section * * @var string */ protected $section = null; /** * Value * * @var mixed */ protected $value = null; /** * Operation * * @var mixed */ protected $operation = null; /** * Set Operation * * @param string $operation +/- * * @return void */ public function setOperation($operation) { $this->operation = $operation; } /** * Get Operation * * @return void */ public function getOperation() { return $this->operation; } /** * Set Section name * * @param string $section Name of section in ini file * * @return void */ public function setSection($section) { $this->section = trim($section); } /** * Set Property * * @param string $property property/key name * * @return void */ public function setProperty($property) { $this->property = $property; } /** * Set Value * * @param string $value Value to set for key in ini file * * @return void */ public function setValue($value) { $this->value = $value; } /** * Get Property * * @return string */ public function getProperty() { return $this->property; } /** * Get Value * * @return string */ public function getValue() { return $this->value; } /** * Get Section * * @return string */ public function getSection() { return $this->section; } } * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ /** * Class for reading/writing ini config file * * This preserves comments etc, unlike parse_ini_file and is based heavily on * a solution provided at: * stackoverflow.com/questions/9594238/good-php-classes-that-manipulate-ini-files * * @category Tasks * @package phing.tasks.ext * @author Ken Guest * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html * @link http://www.phing.info/ */ class IniFileConfig { /** * Lines of ini file * * @var array */ protected $lines = array(); /** * Read ini file * * @param string $file filename * * @return void */ public function read($file) { $this->lines = array(); $section = ''; foreach (file($file) as $line) { if (preg_match('/^\s*(;.*)?$/', $line)) { // comment or whitespace $this->lines[] = array( 'type' => 'comment', 'data' => $line, 'section' => $section ); } elseif (preg_match('/^\s?\[(.*)\]/', $line, $match)) { // section $section = $match[1]; $this->lines[] = array( 'type' => 'section', 'data' => $line, 'section' => $section ); } elseif (preg_match('/^\s*(.*?)\s*=\s*(.*?)\s*$/', $line, $match)) { // entry $this->lines[] = array( 'type' => 'entry', 'data' => $line, 'section' => $section, 'key' => $match[1], 'value' => $match[2] ); } } } /** * Get value of given key in specified section * * @param string $section Section * @param string $key Key * * @return void */ public function get($section, $key) { foreach ($this->lines as $line) { if ($line['type'] != 'entry') { continue; } if ($line['section'] != $section) { continue; } if ($line['key'] != $key) { continue; } return $line['value']; } throw new RuntimeException('Missing Section or Key'); } /** * Set key to value in specified section * * @param string $section Section * @param string $key Key * @param string $value Value * * @return void */ public function set($section, $key, $value) { foreach ($this->lines as &$line) { if ($line['type'] != 'entry') { continue; } if ($line['section'] != $section) { continue; } if ($line['key'] != $key) { continue; } $line['value'] = $value; $line['data'] = $key . " = " . $value . PHP_EOL; return; } throw new RuntimeException('Missing Section or Key'); } /** * Remove key/section from file. * * If key is not specified, then the entire section will be removed. * * @param string $section Section to manipulate/remove * @param string $key Name of key to remove, might be null/empty * * @return void */ public function remove($section, $key) { if ($section == '') { throw new RuntimeException("Section not set."); } if (is_null($key) || ($key == '')) { // remove entire section foreach ($this->lines as $linenum => $line) { if ($line['section'] == $section) { unset($this->lines[$linenum]); } } } else { foreach ($this->lines as $linenum => $line) { if (($line['section'] == $section) && (isset($line['key'])) && ($line['key'] == $key) ) { unset($this->lines[$linenum]); } } } } /** * Write contents out to file * * @param string $file filename * * @return void */ public function write($file) { if (file_exists($file) && !is_writable($file)) { throw new RuntimeException("$file is not writable"); } $fp = fopen($file, 'w'); foreach ($this->lines as $line) { fwrite($fp, $line['data']); } fclose($fp); } } . */ require_once 'phing/tasks/system/FailTask.php'; /** * Exits the active build, giving an additional message * if available. * * @author Hans Lellelid (Phing) * @author Nico Seessle (Ant) * @version $Id: 3b63d08533321a87618f87c564bde9d609b91f36 $ * @package phing.tasks.system */ class ThrowTask extends FailTask { /** * @var Reference */ private $reference = null; /** * @throws BuildException */ public function main() { $reffed = $this->reference !== null ? $this->reference->getReferencedObject($this->getProject()) : null; if ($reffed !== null && $reffed instanceof BuildException) { throw $reffed; } parent::main(); } /** * @param Reference $ref * * @return void */ public function setRefid(Reference $ref) { $this->reference = $ref; } /** * @return Reference */ public function getRefid() { return $this->reference; } } . */ require_once 'phing/tasks/ext/HttpTask.php'; /** * A HTTP request task. * Making an HTTP request and try to match the response against an provided * regular expression. * * @package phing.tasks.ext * @author Benjamin Schultz * @version $Id: ab6a2d3903492a67c2a16f15ae667d8866af6c1e $ * @since 2.4.1 */ class HttpRequestTask extends HttpTask { /** * Holds the regular expression that should match the response * * @var string */ protected $responseRegex = ''; /** * Whether to enable detailed logging * * @var boolean */ protected $verbose = false; /** * Holds the events that will be logged * * @var array */ protected $observerEvents = array( 'connect', 'sentHeaders', 'sentBodyPart', 'receivedHeaders', 'receivedBody', 'disconnect', ); /** * Holds the request method * * @var string */ protected $method = null; /** * Holds additional post parameters for the request * * @var Parameter[] */ protected $postParameters = array(); /** * Sets the response regex * * @param string $regex */ public function setResponseRegex($regex) { $this->responseRegex = $regex; } /** * Sets whether to enable detailed logging * * @param boolean $verbose */ public function setVerbose($verbose) { $this->verbose = StringHelper::booleanValue($verbose); } /** * Sets a list of observer events that will be logged if verbose output is enabled. * * @param string $observerEvents List of observer events */ public function setObserverEvents($observerEvents) { $this->observerEvents = array(); $token = ' ,;'; $ext = strtok($observerEvents, $token); while ($ext !== false) { $this->observerEvents[] = $ext; $ext = strtok($token); } } /** * The setter for the method * @param $method */ public function setMethod($method) { $this->method = $method; } /** * Creates post body parameters for this request * * @return Parameter The created post parameter */ public function createPostParameter() { $num = array_push($this->postParameters, new Parameter()); return $this->postParameters[$num - 1]; } /** * Load the necessary environment for running this task. * * @throws BuildException */ public function init() { parent::init(); $this->authScheme = HTTP_Request2::AUTH_BASIC; // Other dependencies that should only be loaded when class is actually used require_once 'HTTP/Request2/Observer/Log.php'; } /** * Creates and configures an instance of HTTP_Request2 * * @return HTTP_Request2 */ protected function createRequest() { $request = parent::createRequest(); if ($this->method == HTTP_Request2::METHOD_POST) { $request->setMethod(HTTP_Request2::METHOD_POST); foreach ($this->postParameters as $postParameter) { $request->addPostParameter($postParameter->getName(), $postParameter->getValue()); } } if ($this->verbose) { $observer = new HTTP_Request2_Observer_Log(); // set the events we want to log $observer->events = $this->observerEvents; $request->attach($observer); } return $request; } /** * Checks whether response body matches the given regexp * * @param HTTP_Request2_Response $response * @return void * @throws BuildException */ protected function processResponse(HTTP_Request2_Response $response) { if ($this->responseRegex !== '') { $matches = array(); preg_match($this->responseRegex, $response->getBody(), $matches); if (count($matches) === 0) { throw new BuildException('The received response body did not match the given regular expression'); } else { $this->log('The response body matched the provided regex.'); } } } } . */ require_once 'phing/Task.php'; /** * Publish Wiki document using Wiki API. * * @author Piotr Lewandowski * @package phing.tasks.ext */ class WikiPublishTask extends Task { /** * Wiki API url * * @var string */ private $apiUrl; /** * Wiki API user name * * @var string */ private $apiUser; /** * Wiki API password * * @var string */ private $apiPassword; /** * Wiki document Id. Document can be identified by title instead. * * @var int */ private $id; /** * Wiki document title * * @var string */ private $title; /** * Wiki document content * * @var string */ private $content; /** * Publishing mode (append, prepend, overwrite). * * @var string */ private $mode = 'append'; /** * Publish modes map * @var array */ private $modeMap = array( 'overwrite' => 'text', 'append' => 'appendtext', 'prepend' => 'prependtext', ); /** * Curl handler * * @var resource */ private $curl; /** * Wiki api edit token * * @var string */ private $apiEditToken; /** * Temporary cookies file * * @var string */ private $cookiesFile; /** * @param string $apiPassword */ public function setApiPassword($apiPassword) { $this->apiPassword = $apiPassword; } /** * @return string */ public function getApiPassword() { return $this->apiPassword; } /** * @param string $apiUrl */ public function setApiUrl($apiUrl) { $this->apiUrl = $apiUrl; } /** * @return string */ public function getApiUrl() { return $this->apiUrl; } /** * @param string $apiUser */ public function setApiUser($apiUser) { $this->apiUser = $apiUser; } /** * @return string */ public function getApiUser() { return $this->apiUser; } /** * @param int $id */ public function setId($id) { $this->id = $id; } /** * @return int */ public function getId() { return $this->id; } /** * @param string $mode * @throws BuildException */ public function setMode($mode) { if (false === isset($this->modeMap[$mode])) { throw new BuildException('Mode is invalid (' . $mode . ', should be one of ' . implode( ',', array_keys($this->modeMap) ) . ')'); } $this->mode = $mode; } /** * @return string */ public function getMode() { return $this->mode; } /** * @param string $title */ public function setTitle($title) { $this->title = $title; } /** * @return string */ public function getTitle() { return $this->title; } /** * @param string $content */ public function setContent($content) { $this->content = $content; } /** * @return string */ public function getContent() { return $this->content; } /** * Prepare CURL object * * @throws BuildException */ public function init() { $this->cookiesFile = tempnam(sys_get_temp_dir(), 'WikiPublish.' . uniqid() . '.cookies'); $this->curl = curl_init(); if (false === is_resource($this->curl)) { throw new BuildException('Curl init failed (' . $this->apiUrl . ')'); } curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookiesFile); curl_setopt($this->curl, CURLOPT_COOKIEFILE, $this->cookiesFile); } /** * The main entry point method */ public function main() { $this->validateAttributes(); $this->callApiLogin(); $this->callApiEdit(); } /** * Close curl connection and clean up */ public function __destruct() { if (null !== $this->curl && is_resource($this->curl)) { curl_close($this->curl); } if (null !== $this->cookiesFile && file_exists($this->cookiesFile)) { unlink($this->cookiesFile); } } /** * Validates attributes coming in from XML * * @throws BuildException */ private function validateAttributes() { if (null === $this->apiUrl) { throw new BuildException('Wiki apiUrl is required'); } if (null === $this->id && null === $this->title) { throw new BuildException('Wiki page id or title is required'); } } /** * Call Wiki webapi login action * * @param string|null $token * * @throws BuildException */ private function callApiLogin($token = null) { $postData = array('lgname' => $this->apiUser, 'lgpassword' => $this->apiPassword); if (null !== $token) { $postData['lgtoken'] = $token; } $result = $this->callApi('action=login', $postData); try { $this->checkApiResponseResult('login', $result); } catch (BuildException $e) { if (null !== $token) { throw $e; } // if token is required then call login again with token $this->checkApiResponseResult('login', $result, 'NeedToken'); if (isset($result['login']) && isset($result['login']['token'])) { $this->callApiLogin($result['login']['token']); } else { throw $e; } } } /** * Call Wiki webapi edit action */ private function callApiEdit() { $this->callApiTokens(); $result = $this->callApi('action=edit&token=' . urlencode($this->apiEditToken), $this->getApiEditData()); $this->checkApiResponseResult('edit', $result); } /** * Return prepared data for Wiki webapi edit action * * @return array */ private function getApiEditData() { $result = array( 'minor' => '', ); if (null !== $this->title) { $result['title'] = $this->title; } if (null !== $this->id) { $result['pageid'] = $this->id; } $result[$this->modeMap[$this->mode]] = $this->content; return $result; } /** * Call Wiki webapi tokens action * * @throws BuildException */ private function callApiTokens() { $result = $this->callApi('action=tokens&type=edit'); if (false == isset($result['tokens']) || false == isset($result['tokens']['edittoken'])) { throw new BuildException('Wiki token not found'); } $this->apiEditToken = $result['tokens']['edittoken']; } /** * Call Wiki webapi * * @param string $queryString * @param array|null $postData * * @return array * @throws BuildException */ protected function callApi($queryString, $postData = null) { $this->setPostData($postData); $url = $this->apiUrl . '?' . $queryString . '&format=php'; curl_setopt($this->curl, CURLOPT_URL, $url); $response = curl_exec($this->curl); $responseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); if (200 !== $responseCode) { throw new BuildException('Wiki webapi call failed (http response ' . $responseCode . ')'); } $result = @unserialize($response); if (false === $result) { throw new BuildException('Couldn\'t unserialize Wiki webapi response'); } return $result; } /** * Set POST data for curl call * * @param array|null $data */ private function setPostData($data = null) { if (null === $data) { curl_setopt($this->curl, CURLOPT_POST, false); return; } $postData = ''; foreach ($data as $key => $value) { $postData .= urlencode($key) . '=' . urlencode($value) . '&'; } if ($postData != '') { curl_setopt($this->curl, CURLOPT_POST, true); curl_setopt($this->curl, CURLOPT_POSTFIELDS, substr($postData, 0, -1)); } } /** * Validate Wiki webapi response * * @param string $action * @param array $response * @param string $expect * * @throws BuildException */ private function checkApiResponseResult($action, $response, $expect = 'Success') { if (isset($response['error'])) { throw new BuildException( 'Wiki response error (action: ' . $action . ', error code: ' . $response['error']['code'] . ')'); } if (false == isset($response[$action]) || false == isset($response[$action]['result'])) { throw new BuildException('Wiki response result not found (action: ' . $action . ')'); } if ($response[$action]['result'] !== $expect) { throw new BuildException( 'Unexpected Wiki response result ' . $response[$action]['result'] . ' (expected: ' . $expect . ')'); } } } . */ require_once dirname(dirname(__FILE__)) . '/S3.php'; /** * Stores an object on S3 * * @version $Id: 37e9c57cc495b2eb764a5bbd6221a7d6ad115127 $ * @package phing.tasks.ext * @author Andrei Serdeliuc * @extends Service_Amazon_S3 */ class S3PutTask extends Service_Amazon_S3 { /** * File we're trying to upload * * (default value: null) * * @var string */ protected $_source = null; /** * Content we're trying to upload * * The user can specify either a file to upload or just a bit of content * * (default value: null) * * @var mixed */ protected $_content = null; /** * Collection of filesets * Used for uploading multiple files * * (default value: array()) * * @var array */ protected $_filesets = array(); /** * Whether to try to create buckets or not * * (default value: false) * * @var bool */ protected $_createBuckets = false; /** * File ACL * Use to set the permission to the uploaded files * * (default value: 'private') * * @var string */ protected $_acl = 'private'; /** * File content type * Use this to set the content type of your static files * Set contentType to "auto" if you want to autodetect the content type based on the source file extension * * (default value: 'binary/octet-stream') * * @var string */ protected $_contentType = 'binary/octet-stream'; /** * Object maxage (in seconds). * * @var int */ protected $_maxage = null; /** * Content is gzipped. * * @var boolean */ protected $_gzipped = false; /** * Extension content type mapper * * @var array */ protected $_extensionContentTypeMapper = array( 'js' => 'application/x-javascript', 'css' => 'text/css', 'html' => 'text/html', 'gif' => 'image/gif', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'txt' => 'text/plain' ); /** * Whether filenames contain paths * * (default value: false) * * @var bool */ protected $_fileNameOnly = false; /** * @param $source * @throws BuildException */ public function setSource($source) { if (!is_readable($source)) { throw new BuildException('Source is not readable: ' . $source); } $this->_source = $source; } /** * @return string * @throws BuildException */ public function getSource() { if ($this->_source === null) { throw new BuildException('Source is not set'); } return $this->_source; } /** * @param $content * @throws BuildException */ public function setContent($content) { if (empty($content) || !is_string($content)) { throw new BuildException('Content must be a non-empty string'); } $this->_content = $content; } /** * @return mixed * @throws BuildException */ public function getContent() { if ($this->_content === null) { throw new BuildException('Content is not set'); } return $this->_content; } /** * @param $object * @throws BuildException */ public function setObject($object) { if (empty($object) || !is_string($object)) { throw new BuildException('Object must be a non-empty string'); } $this->_object = $object; } public function getObject() { if ($this->_object === null) { throw new BuildException('Object is not set'); } return $this->_object; } /** * @param $permission * @throws BuildException */ public function setAcl($permission) { $valid_acl = array('private', 'public-read', 'public-read-write', 'authenticated-read'); if (empty($permission) || !is_string($permission) || !in_array($permission, $valid_acl)) { throw new BuildException('Object must be one of the following values: ' . implode('|', $valid_acl)); } $this->_acl = $permission; } /** * @return string */ public function getAcl() { return $this->_acl; } /** * @param $contentType */ public function setContentType($contentType) { $this->_contentType = $contentType; } /** * @return string * @throws BuildException */ public function getContentType() { if ($this->_contentType === 'auto') { $ext = strtolower(substr(strrchr($this->getSource(), '.'), 1)); if (isset($this->_extensionContentTypeMapper[$ext])) { return $this->_extensionContentTypeMapper[$ext]; } else { return 'binary/octet-stream'; } } else { return $this->_contentType; } } /** * @param $createBuckets */ public function setCreateBuckets($createBuckets) { $this->_createBuckets = (bool) $createBuckets; } /** * @return bool */ public function getCreateBuckets() { return (bool) $this->_createBuckets; } /** * Set seconds in max-age, null value exclude max-age setup. * * @param int $seconds */ public function setMaxage($seconds) { $this->_maxage = $seconds; } /** * Get seconds in max-age or null. * * @return int * Number of seconds in maxage or null. */ public function getMaxage() { return $this->_maxage; } /** * Set if content is gzipped. * * @param boolean $gzipped */ public function setGzip($gzipped) { $this->_gzipped = $gzipped; } /** * Return if content is gzipped. * * @return booleand * Indicate if content is gzipped. */ public function getGzip() { return $this->_gzipped; } /** * Generate HTTPHEader array sent to S3. * * @return array * HttpHeader to set in S3 Object. */ protected function getHttpHeaders() { $headers = array(); if (!is_null($this->_maxage)) { $headers['Cache-Control'] = 'max-age=' . $this->_maxage; } if ($this->_gzipped) { $headers['Content-Encoding'] = 'gzip'; } return $headers; } /** * @param $fileNameOnly */ public function setFileNameOnly($fileNameOnly) { $this->_fileNameOnly = (bool) $fileNameOnly; } /** * creator for _filesets * * @return FileSet */ public function createFileset() { $num = array_push($this->_filesets, new FileSet()); return $this->_filesets[$num - 1]; } /** * getter for _filesets * * @return array */ public function getFilesets() { return $this->_filesets; } /** * Determines what we're going to store in the object * * If _content has been set, this will get stored, * otherwise, we read from _source * * @throws BuildException * @return string */ public function getObjectData() { try { $content = $this->getContent(); } catch (BuildException $e) { $source = $this->getSource(); if (!is_file($source)) { throw new BuildException('Currently only files can be used as source'); } $content = file_get_contents($source); } return $content; } /** * Store the object on S3 * * @throws BuildException * @return void */ public function execute() { if (!$this->isBucketAvailable()) { if (!$this->getCreateBuckets()) { throw new BuildException('Bucket doesn\'t exist and createBuckets not specified'); } else { if (!$this->createBucket()) { throw new BuildException('Bucket cannot be created'); } } } // Filesets take precedence if (!empty($this->_filesets)) { $objects = array(); foreach ($this->_filesets as $fs) { if (!($fs instanceof FileSet)) { continue; } $ds = $fs->getDirectoryScanner($this->getProject()); $objects = array_merge($objects, $ds->getIncludedFiles()); } $fromDir = $fs->getDir($this->getProject())->getAbsolutePath(); if ($this->_fileNameOnly) { foreach ($objects as $object) { $this->_source = $object; $this->saveObject(basename($object), file_get_contents($fromDir . DIRECTORY_SEPARATOR . $object)); } } else { foreach ($objects as $object) { $this->_source = $object; $this->saveObject( str_replace('\\', '/', $object), file_get_contents($fromDir . DIRECTORY_SEPARATOR . $object) ); } } return true; } $this->saveObject($this->getObject(), $this->getObjectData()); } /** * @param $object * @param $data * @throws BuildException */ protected function saveObject($object, $data) { $object = $this->getObjectInstance($object); $object->data = $data; $object->acl = $this->getAcl(); $object->contentType = $this->getContentType(); $object->httpHeaders = $this->getHttpHeaders(); $object->save(); if (!$this->isObjectAvailable($object->key)) { throw new BuildException('Upload failed'); } } } . */ require_once dirname(dirname(__FILE__)) . '/S3.php'; /** * Downloads an object off S3 * * @version $Id: 755f7c3784838bc960dba9520a10490c640a61cd $ * @package phing.tasks.ext * @author Andrei Serdeliuc * @extends Service_Amazon_S3 */ class S3GetTask extends Service_Amazon_S3 { /** * This is where we'll store the object * * (default value: null) * * @var mixed */ protected $_target = null; /** * The S3 object we're working with * * (default value: null) * * @var mixed */ protected $_object = null; /** * @param $object * @throws BuildException */ public function setObject($object) { if (empty($object) || !is_string($object)) { throw new BuildException('Object must be a non-empty string'); } $this->_object = $object; } /** * @return mixed * @throws BuildException */ public function getObject() { if ($this->_object === null) { throw new BuildException('Object is not set'); } return $this->_object; } /** * @param $target * @throws BuildException */ public function setTarget($target) { if (!is_file($target) && !is_dir($target) && !is_link($target)) { if (!is_writable(dirname($target))) { throw new BuildException('Target is not writable: ' . $target); } } else { if (!is_writable($target)) { throw new BuildException('Target is not writable: ' . $target); } } $this->_target = $target; } /** * @return mixed * @throws BuildException */ public function getTarget() { if ($this->_target === null) { throw new BuildException('Target is not set'); } return $this->_target; } public function execute() { $target = $this->getTarget(); // Use the object name as the target if the current target is a directory if (is_dir($target)) { $target = rtrim($target, '/') . '/' . $this->getObject(); } file_put_contents($target, $this->getObjectContents($this->getObject())); } } . */ require_once dirname(dirname(__FILE__)) . "/Amazon.php"; /** * Abstract Service_Amazon_S3 class. * * Provides common methods and properties to all of the S3 tasks * * @version $ID$ * @package phing.tasks.ext * @author Andrei Serdeliuc */ abstract class Service_Amazon_S3 extends Service_Amazon { /** * Services_Amazon_S3 client * * (default value: null) * * @var Services_Amazon_S3 * @see Services_Amazon_S3 */ protected $_client = null; /** * We only instantiate the client once per task call * * @return Services_Amazon_S3 */ public function getClient() { require_once "Services/Amazon/S3.php"; if ($this->_client === null) { $this->_client = Services_Amazon_S3::getAccount($this->getKey(), $this->getSecret()); } return $this->_client; } /** * @param $bucket * @throws BuildException */ public function setBucket($bucket) { if (empty($bucket) || !is_string($bucket)) { throw new BuildException('Bucket must be a non-empty string'); } $this->bucket = (string) $bucket; } /** * @throws BuildException */ public function getBucket() { if (!($bucket = $this->bucket)) { throw new BuildException('Bucket is not set'); } return $this->bucket; } /** * Returns an instance of Services_Amazon_S3_Resource_Object * * @param mixed $object * @return Services_Amazon_S3_Resource_Object */ public function getObjectInstance($object) { return $this->getBucketInstance()->getObject($object); } /** * Check if the object already exists in the current bucket * * @param mixed $object * @return bool */ public function isObjectAvailable($object) { return (bool) $this->getObjectInstance($object)->load(Services_Amazon_S3_Resource_Object::LOAD_METADATA_ONLY); } /** * Returns an instance of Services_Amazon_S3_Resource_Bucket * * @return Services_Amazon_S3_Resource_Bucket */ public function getBucketInstance() { return $this->getClient()->getBucket($this->getBucket()); } /** * Check if the current bucket is available * * @return bool */ public function isBucketAvailable() { return (bool) $this->getBucketInstance($this->getBucket())->load(); } /** * Get the contents of an object (by it's name) * * @param string $object * @throws BuildException * @return mixed */ public function getObjectContents($object) { if (!$this->isBucketAvailable($this->getBucket())) { throw new BuildException('Bucket doesn\'t exist or wrong permissions'); } $bucket = $this->getClient()->getBucket($this->getBucket()); if (!$this->isObjectAvailable($object)) { throw new BuildException('Object not available: ' . $object); } $object = $this->getObjectInstance($object); $object->load(); return $object->data; } /** * Create a bucket * * @return bool */ public function createBucket() { $bucket = $this->getBucketInstance(); $bucket->name = $this->getBucket(); $bucket->save(); return $this->isBucketAvailable(); } /** * Main entry point, doesn't do anything * * @return void */ final public function main() { $this->execute(); } /** * Entry point to children tasks * * @return void */ abstract public function execute(); } . */ require_once "phing/Task.php"; /** * Abstract Service_Amazon class. * * Implements common methods & properties used by all Amazon services * * @extends Task * @version $ID$ * @package phing.tasks.ext * @author Andrei Serdeliuc * @abstract */ abstract class Service_Amazon extends Task { /** * Collection of set options * * We set these magically so we can also load then from the environment * * (default value: array()) * * @var array */ protected $_options = array(); /** * @param $var * @param $val */ public function __set($var, $val) { $this->_options[$var] = $val; } /** * Property getter * * If the property hasn't been previously set (through the task call normally), * it will try to load it from the project * * This way, we can define global properties for the "Amazon" service, like key and secret * * @param mixed $var * @return mixed */ public function __get($var) { if (!isset($this->$var)) { if (!($val = $this->getProject()->getProperty('amazon.' . strtolower($var)))) { return false; } else { return $val; } } return $this->_options[$var]; } /** * @param $var * @return bool */ public function __isset($var) { return array_key_exists($var, $this->_options); } /** * @param $key * @throws BuildException */ public function setKey($key) { if (empty($key) || !is_string($key)) { throw new BuildException('Key must be a non empty string'); } $this->key = $key; } public function getKey() { if (!($key = $this->key)) { throw new BuildException('Key is not set'); } return $key; } /** * @param $secret * @throws BuildException */ public function setSecret($secret) { if (empty($secret) || !is_string($secret)) { throw new BuildException('Secret must be a non empty string'); } $this->secret = $secret; } public function getSecret() { if (!($secret = $this->secret)) { throw new BuildException('Secret is not set'); } return $this->secret; } } patchFile = $file; } /** * The file to patch * * Optional if it can be inferred from the diff file. * * @param string $file File to patch * @return void */ public function setOriginalFile($file) { $this->originalFile = $file; } /** * The name of a file to send the output to, instead of patching * the file(s) in place * * Optional. * * @param string $file File to send the output to * @return void */ public function setDestFile($file) { if ($file !== null) { $this->cmdArgs [] = "--output=$file"; } } /** * Flag to create backups * * Optional, default - false * * @param bool $backups If true create backups * @return void */ public function setBackups($backups) { if ($backups) { $this->cmdArgs [] = '--backup'; } } /** * Flag to ignore whitespace differences; * * Default - false * * @param bool $ignore If true ignore whitespace differences * @return void */ public function setIgnoreWhiteSpace($ignore) { if ($ignore) { $this->cmdArgs [] = '--ignore-whitespace'; } } /** * Strip the smallest prefix containing num leading slashes * from filenames. * * patch's --strip option. * * @param int $num number of lines to strip * @return void * @throws BuildException if num is < 0, or other errors */ public function setStrip($num) { if ($num < 0) { throw new BuildException('strip has to be >= 0'); } $this->strip = $num; } /** * Work silently unless an error occurs * * Optional, default - false * @param bool $flag If true suppress set the -s option on the patch command * @return void */ public function setQuiet($flag) { if ($flag) { $this->cmdArgs [] = '--silent'; } } /** * Assume patch was created with old and new files swapped * * Optional, default - false * * @param bool $flag If true set the -R option on the patch command * @return void */ public function setReverse($flag) { if ($flag) { $this->cmdArgs [] = '--reverse'; } } /** * The directory to run the patch command in * * Defaults to the project's base directory. * * @param string $directory Directory to run the patch command in * @return void */ public function setDir($directory) { $this->cmdArgs [] = "--directory=$directory"; } /** * Ignore patches that seem to be reversed or already applied * * @param bool $flag If true set the -N (--forward) option * @return void */ public function setForward($flag) { if ($flag) { $this->cmdArgs [] = "--forward"; } } /** * Set the maximum fuzz factor * * Defaults to 0 * * @param string $value Value of a fuzz factor * @return void */ public function setFuzz($value) { $this->cmdArgs [] = "--fuzz=$value"; } /** * If true, stop the build process if the patch command * exits with an error status. * * The default is "false" * * @param bool $value "true" if it should halt, otherwise "false" * @return void */ public function setHaltOnFailure($value) { $this->haltOnFailure = $value; } /** * Main task method * * @return void * @throws BuildException when it all goes a bit pear shaped */ public function main() { if ($this->patchFile == null) { throw new BuildException('patchfile argument is required'); } // Define patch file $this->cmdArgs [] = '-i ' . $this->patchFile; // Define strip factor if ($this->strip != null) { $this->cmdArgs [] = '--strip=' . $this->strip; } // Define original file if specified if ($this->originalFile != null) { $this->cmdArgs [] = $this->originalFile; } $cmd = self::CMD . implode(' ', $this->cmdArgs); $this->log('Applying patch: ' . $this->patchFile); exec($cmd, $output, $exitCode); foreach ($output as $line) { $this->log($line, Project::MSG_VERBOSE); } if ($exitCode != 0 && $this->haltOnFailure) { throw new BuildException("Task exited with code $exitCode"); } } } . */ /** * Remove from cache files where contains errors * * @category PHP * @package PHP_CodeSniffer * @author Rui Filipe Da Cunha Alves */ class PHP_CodeSniffer_Reports_PhingRemoveFromCache implements PHP_CodeSniffer_Report { /** * Cache data storage * @var DataStore */ protected static $cache; /** * Set cache object * * @param DataStore $cache */ public static function setCache($cache) { self::$cache = $cache; } /** * Remove file from cache if contains errors * * @param array $report Prepared report data. * @param PHP_CodeSniffer_File $phpcsFile The file being reported on. * @param boolean $showSources Show sources? * @param int $width Maximum allowed line width. * * @return boolean */ public function generateFileReport( $report, PHP_CodeSniffer_File $phpcsFile, $showSources = false, $width = 80 ) { if (!self::$cache || ($report['errors'] === 0 && $report['warnings'] === 0)) { // Nothing to do return false; } self::$cache->remove($report['filename']); return false; } /** * Do nothing * * @param string $cachedData Any partial report data that was returned from * generateFileReport during the run. * @param int $totalFiles Total number of files processed during the run. * @param int $totalErrors Total number of errors found during the run. * @param int $totalWarnings Total number of warnings found during the run. * @param int $totalFixable Total number of problems that can be fixed. * @param boolean $showSources Show sources? * @param int $width Maximum allowed line width. * @param boolean $toScreen Is the report being printed to screen? * * @return void */ public function generate( $cachedData, $totalFiles, $totalErrors, $totalWarnings, $totalFixable, $showSources = false, $width = 80, $toScreen = true ) { // Do nothing } } . */ require_once 'phing/Task.php'; /** * Wrapper to disable PHPCS's destructor * * @author Michiel Rook * @version $Id: 0165de67f7d92e363d668430c692ab7f3658dec6 $ * @package phing.tasks.ext */ class PhpCodeSnifferTask_Wrapper extends PHP_CodeSniffer { public function __destruct() { // override destructor } } . */ require_once 'phing/Task.php'; require_once 'phing/util/DataStore.php'; /** * A Javascript lint task. Checks syntax of Javascript files. * Javascript lint (http://www.javascriptlint.com) must be in the system path. * This class is based on Knut Urdalen's PhpLintTask. * * @author Stefan Priebsch * * @package phing.tasks.ext */ class JslLintTask extends Task { /** @var PhingFile */ protected $file; // the source file (from xml attribute) /** @var array */ protected $filesets = array(); // all fileset objects assigned to this task /** @var bool $showWarnings */ protected $showWarnings = true; /** @var bool */ protected $haltOnFailure = false; /** * @var bool */ protected $haltOnWarning = false; /** * @var bool */ protected $hasErrors = false; /** * @var bool */ protected $hasWarnings = false; /** @var array $badFiles */ private $badFiles = array(); /** @var DataStore */ private $cache = null; /** @var PhingFile */ private $conf = null; /** @var string */ private $executable = "jsl"; /** @var PhingFile */ protected $tofile = null; /** * Sets the flag if warnings should be shown * * @param boolean $show */ public function setShowWarnings($show) { $this->showWarnings = StringHelper::booleanValue($show); } /** * The haltonfailure property * * @param boolean $aValue */ public function setHaltOnFailure($aValue) { $this->haltOnFailure = $aValue; } /** * The haltonwarning property * * @param boolean $aValue */ public function setHaltOnWarning($aValue) { $this->haltOnWarning = $aValue; } /** * File to be performed syntax check on * * @param PhingFile $file */ public function setFile(PhingFile $file) { $this->file = $file; } /** * Whether to store last-modified times in cache * * @param PhingFile $file */ public function setCacheFile(PhingFile $file) { $this->cache = new DataStore($file); } /** * jsl config file * * @param PhingFile $file */ public function setConfFile(PhingFile $file) { $this->conf = $file; } /** * @param string $path * * @throws BuildException */ public function setExecutable($path) { $this->executable = $path; if (!@file_exists($path)) { throw new BuildException("JavaScript Lint executable '{$path}' not found"); } } /** * @return string */ public function getExecutable() { return $this->executable; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * File to save error messages to * * @param PhingFile $tofile */ public function setToFile(PhingFile $tofile) { $this->tofile = $tofile; } /** * Execute lint check against PhingFile or a FileSet */ public function main() { if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException("Missing either a nested fileset or attribute 'file' set"); } if (empty($this->executable)) { throw new BuildException("Missing the 'executable' attribute"); } if ($this->file instanceof PhingFile) { $this->lint($this->file->getPath()); } else { // process filesets $project = $this->getProject(); foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($project); $files = $ds->getIncludedFiles(); $dir = $fs->getDir($this->project)->getPath(); foreach ($files as $file) { $this->lint($dir . DIRECTORY_SEPARATOR . $file); } } } // write list of 'bad files' to file (if specified) if ($this->tofile) { $writer = new FileWriter($this->tofile); foreach ($this->badFiles as $file => $messages) { foreach ($messages as $msg) { $writer->write($file . "=" . $msg . PHP_EOL); } } $writer->close(); } if ($this->haltOnFailure && $this->hasErrors) { throw new BuildException('Syntax error(s) in JS files:' . implode( ', ', array_keys($this->badFiles) )); } if ($this->haltOnWarning && $this->hasWarnings) { throw new BuildException('Syntax warning(s) in JS files:' . implode( ', ', array_keys($this->badFiles) )); } } /** * Performs the actual syntax check * * @param string $file * * @throws BuildException * * @return bool|void */ protected function lint($file) { $command = $this->executable . ' -output-format ' . escapeshellarg( 'file:__FILE__;line:__LINE__;message:__ERROR__' ) . ' '; if (isset($this->conf)) { $command .= '-conf ' . escapeshellarg($this->conf->getPath()) . ' '; } $command .= '-process '; if (file_exists($file)) { if (is_readable($file)) { if ($this->cache) { $lastmtime = $this->cache->get($file); if ($lastmtime >= filemtime($file)) { $this->log("Not linting '" . $file . "' due to cache", Project::MSG_DEBUG); return false; } } $messages = array(); exec($command . '"' . $file . '"', $messages, $return); if ($return > 100) { throw new BuildException("Could not execute Javascript Lint executable '{$this->executable}'"); } $summary = $messages[sizeof($messages) - 1]; preg_match('/(\d+)\serror/', $summary, $matches); $errorCount = (count($matches) > 1 ? $matches[1] : 0); preg_match('/(\d+)\swarning/', $summary, $matches); $warningCount = (count($matches) > 1 ? $matches[1] : 0); $errors = array(); $warnings = array(); if ($errorCount > 0 || $warningCount > 0) { $last = false; foreach ($messages as $message) { $matches = array(); if (preg_match('/^(\.*)\^$/', $message)) { $column = strlen($message); if ($last == 'error') { $errors[count($errors) - 1]['column'] = $column; } else { if ($last == 'warning') { $warnings[count($warnings) - 1]['column'] = $column; } } $last = false; } if (!preg_match('/^file:(.+);line:(\d+);message:(.+)$/', $message, $matches)) { continue; } $msg = $matches[3]; $data = array('filename' => $matches[1], 'line' => $matches[2], 'message' => $msg); if (preg_match('/^.*error:.+$/i', $msg)) { $errors[] = $data; $last = 'error'; } else { if (preg_match('/^.*warning:.+$/i', $msg)) { $warnings[] = $data; $last = 'warning'; } } } } if ($this->showWarnings && $warningCount > 0) { $this->log($file . ': ' . $warningCount . ' warnings detected', Project::MSG_WARN); foreach ($warnings as $warning) { $this->log( '- line ' . $warning['line'] . (isset($warning['column']) ? ' column ' . $warning['column'] : '') . ': ' . $warning['message'], Project::MSG_WARN ); } $this->hasWarnings = true; } if ($errorCount > 0) { $this->log($file . ': ' . $errorCount . ' errors detected', Project::MSG_ERR); if (!isset($this->badFiles[$file])) { $this->badFiles[$file] = array(); } foreach ($errors as $error) { $message = 'line ' . $error['line'] . (isset($error['column']) ? ' column ' . $error['column'] : '') . ': ' . $error['message']; $this->log('- ' . $message, Project::MSG_ERR); array_push($this->badFiles[$file], $message); } $this->hasErrors = true; } else { if (!$this->showWarnings || $warningCount == 0) { $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); if ($this->cache) { $this->cache->put($file, filemtime($file)); } } } } else { throw new BuildException('Permission denied: ' . $file); } } else { throw new BuildException('File not found: ' . $file); } } } . */ require_once 'phing/Task.php'; /** * Convert dot-notation packages to relative paths. * * @author Hans Lellelid * @version $Id: 7fee76167437d1ca7bdca2fef13aafc08811085f $ * @package phing.tasks.ext */ class PackageAsPathTask extends Task { /** The package to convert. */ protected $pckg; /** The property to store the conversion in. */ protected $name; /** * Executes the package to patch converstion and stores it * in the user property name. */ public function main() { $this->project->setUserProperty($this->name, strtr($this->pckg, '.', '/')); } /** * @param string $pckg the package to convert */ public function setPackage($pckg) { $this->pckg = $pckg; } /** * @param string $name the property to store the path in */ public function setName($name) { $this->name = $name; } } . */ require_once 'phing/Task.php'; /** * ZendCodeAnalyzerTask analyze PHP source code using the ZendCodeAnalyzer included in Zend Studio 5.1 * * Available warnings: * zend-error - %s(line %d): %s * oneline-comment - One-line comment ends with tag. * bool-assign - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='? * bool-print - Print statement used when boolean expression is expected. * bool-array - Array used when boolean expression is expected. * bool-object - Object used when boolean expression is expected. * call-time-ref - Call-time reference is deprecated. Define function as accepting parameter by reference instead. * if-if-else - In if-if-else construction else relates to the closest if. Use braces to make the code clearer. * define-params - define() requires two or three parameters. * define-const - First parameter for define() should be string. Maybe you forgot quotes? * break-var - Break/continue with variable is dangerous - break level can be out of scope. * break-depth - Break/continue with depth more than current nesting level. * var-once - Variable '%s' encountered only once. May be a typo? * var-arg-unused - Function argument '%s' is never used. * var-global-unused - Global variable '%s' is defined but never used. * var-use-before-def - Variable '%s' is used before it was assigned. * var-use-before-def-global - Global variable '%s' is used without being assigned. You are probably relying on register_globals feature of PHP. Note that this feature is off by default. * var-no-global - PHP global variable '%s' is used as local. Maybe you wanted to define '%s' as global? * var-value-unused - Value assigned to variable '%s' is never used * var-ref-notmodified - Function parameter '%s' is passed by reference but never modified. Consider passing by value. * return-empty-val - Function '%s' has both empty return and return with value. * return-empty-used - Function '%s' has empty return but return value is used. * return-noref - Function '%s' returns reference but the value is not assigned by reference. Maybe you meant '=&' instead of '='? * return-end-used - Control reaches the end of function '%s'(file %s, line %d) but return value is used. * sprintf-miss-args - Missing arguments for sprintf: format reqires %d arguments but %d are supplied. * sprintf-extra-args - Extra arguments for sprintf: format reqires %d arguments but %d are supplied. * unreach-code - Unreachable code in function '%s'. * include-var - include/require with user-accessible variable can be dangerous. Consider using constant instead. * non-object - Variable '%s' used as object, but has different type. * bad-escape - Bad escape sequence: \%c, did you mean \\%c? * empty-cond - Condition without a body * expr-unused - Expression result is never used * * @author Knut Urdalen * @version $Id: d1bcb58746c4f9bb6e63c43e61c9074f511ad456 $ * @package phing.tasks.ext */ class ZendCodeAnalyzerTask extends Task { protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary protected $file = ""; // the source file (from xml attribute) protected $filesets = array(); // all fileset objects assigned to this task protected $counter = 0; protected $disable = array(); protected $enable = array(); private $haltonwarning = false; /** * File to be analyzed * * @param PhingFile $file */ public function setFile(PhingFile $file) { $this->file = $file; } /** * Path to ZendCodeAnalyzer binary * * @param string $analyzerPath */ public function setAnalyzerPath($analyzerPath) { $this->analyzerPath = $analyzerPath; } /** * Disable warning levels. Separate warning levels with ',' * * @param string $disable */ public function setDisable($disable) { $this->disable = explode(",", $disable); } /** * Enable warning levels. Separate warning levels with ',' * * @param string $enable */ public function setEnable($enable) { $this->enable = explode(",", $enable); } /** * Sets the haltonwarning flag * @param boolean $value */ public function setHaltonwarning($value) { $this->haltonwarning = $value; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * Analyze against PhingFile or a FileSet */ public function main() { if (!isset($this->analyzerPath)) { throw new BuildException("Missing attribute 'analyzerPath'"); } if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException("Missing either a nested fileset or attribute 'file' set"); } if ($this->file instanceof PhingFile) { $this->analyze($this->file->getPath()); } else { // process filesets $project = $this->getProject(); foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($project); $files = $ds->getIncludedFiles(); $dir = $fs->getDir($this->project)->getPath(); foreach ($files as $file) { $this->analyze($dir . DIRECTORY_SEPARATOR . $file); } } } $this->log("Number of findings: " . $this->counter, Project::MSG_INFO); } /** * Analyze file * * @param string $file * @throws BuildException * @return void */ protected function analyze($file) { if (file_exists($file)) { if (is_readable($file)) { // Construct shell command $cmd = $this->analyzerPath . " "; foreach ($this->enable as $enable) { // Enable warning levels $cmd .= " --enable $enable "; } foreach ($this->disable as $disable) { // Disable warning levels $cmd .= " --disable $disable "; } $cmd .= "$file 2>&1"; // Execute command $result = shell_exec($cmd); $result = explode("\n", $result); for ($i = 2, $size = count($result); $i < ($size - 1); $i++) { $this->counter++; $this->log($result[$i], Project::MSG_WARN); } $total = count($result) - 3; if ($total > 0 && $this->haltonwarning) { throw new BuildException('zendcodeanalyzer detected ' . $total . ' warning' . ($total > 1 ? 's' : '') . ' in ' . $file); } } else { throw new BuildException('Permission denied: ' . $file); } } else { throw new BuildException('File not found: ' . $file); } } } . */ include_once 'phing/system/io/PhingFile.php'; /** * Builds list of files for PEAR_PackageFileManager using a Phing FileSet. * * Some code here is taken from PEAR_PackageFileManager_File -- getting results from flat * array into the assoc array expected from getFileList(). * * @author Greg Beaver * @author Hans Lellelid * @package phing.tasks.ext.pearpackage * @version $Id: 4287f56d47c2d793bc22417402f8c37daf3745f3 $ */ class PEAR_PackageFileManager_Fileset { /** * Current Phing Project. * @var Project */ private $project; /** * FileSets to use. * @var array FileSet[] */ private $filesets = array(); /** * Set up the FileSet filelist generator * * 'project' and 'filesets' are the only options that this class uses. * * @param PEAR_PackageFileManager * @param array */ public function __construct($options) { if (!is_array($options)) { $options = $options->getOptions(); } $this->project = $options['phing_project']; $this->filesets = $options['phing_filesets']; } /** * Generate the section * of the package file. * * This function performs the backend generation of the array * containing all files in this package * @return array structure of all files to include */ public function getFileList() { $allfiles = array(); foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($this->project); $files = $ds->getIncludedFiles(); // We need to store these files keyed by the basedir from DirectoryScanner // so that we can resolve the fullpath of the file later. if (isset($allfiles[$ds->getBasedir()])) { $allfiles[$ds->getBasedir()] = array_merge($allfiles[$ds->getBasedir()], $files); } else { $allfiles[$ds->getBasedir()] = $files; } } $struc = array(); foreach ($allfiles as $basedir => $files) { foreach ($files as $file) { // paths are relative to $basedir above $path = strtr(dirname($file), DIRECTORY_SEPARATOR, '/'); if (!$path || $path == '.') { $path = '/'; // for array index } $parts = explode('.', basename($file)); $ext = array_pop($parts); if (strlen($ext) == strlen($file)) { $ext = ''; } $f = new PhingFile($basedir, $file); $struc[$path][] = array( 'file' => basename($file), 'ext' => $ext, 'path' => (($path == '/') ? basename($file) : $path . '/' . basename($file)), 'fullpath' => $f->getAbsolutePath() ); } } uksort($struc, 'strnatcasecmp'); foreach ($struc as $key => $ind) { usort($ind, array($this, 'sortfiles')); $struc[$key] = $ind; } $tempstruc = $struc; $struc = array('/' => $tempstruc['/']); $bv = 0; foreach ($tempstruc as $key => $ind) { $save = $key; if ($key != '/') { $struc['/'] = $this->setupDirs($struc['/'], explode('/', $key), $tempstruc[$key]); } } uksort($struc['/'], array($this, 'mystrucsort')); return $struc; } /** * Recursively move contents of $struc into associative array * * The contents of $struc have many indexes like 'dir/subdir/subdir2'. * This function converts them to * array('dir' => array('subdir' => array('subdir2'))) * @param array $struc is array('dir' => array of files in dir, * 'dir/subdir' => array of files in dir/subdir,...) * @param $dir * @param $contents * @internal param array $array form of 'dir/subdir/subdir2' array('dir','subdir','subdir2') * @return array same as struc but with array('dir' => * array(file1,file2,'subdir' => array(file1,...))) */ private function setupDirs($struc, $dir, $contents) { if (!count($dir)) { foreach ($contents as $dir => $files) { if (is_string($dir)) { if (strpos($dir, '/')) { $test = true; $a = $contents[$dir]; unset($contents[$dir]); $b = explode('/', $dir); $c = array_shift($b); if (isset($contents[$c])) { $contents[$c] = $this->setDir($contents[$c], $this->setupDirs(array(), $b, $a)); } else { $contents[$c] = $this->setupDirs(array(), $b, $a); } } } } return $contents; } $me = array_shift($dir); if (!isset($struc[$me])) { $struc[$me] = array(); } $struc[$me] = $this->setupDirs($struc[$me], $dir, $contents); return $struc; } /** * Recursively add all the subdirectories of $contents to $dir without erasing anything in * $dir * @param array * @param array * @return array processed $dir */ public function setDir($dir, $contents) { while (list($one, $two) = each($contents)) { if (isset($dir[$one])) { $dir[$one] = $this->setDir($dir[$one], $contents[$one]); } else { $dir[$one] = $two; } } return $dir; } /** * Sorting functions for the file list * @param string * @param string * @return int */ private function sortfiles($a, $b) { return strnatcasecmp($a['file'], $b['file']); } /** * @param $a * @param $b * @return int */ private function mystrucsort($a, $b) { if (is_numeric($a) && is_string($b)) { return 1; } if (is_numeric($b) && is_string($a)) { return -1; } if (is_numeric($a) && is_numeric($b)) { if ($a > $b) { return 1; } if ($a < $b) { return -1; } if ($a == $b) { return 0; } } return strnatcasecmp($a, $b); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg init * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgInitTask.php */ class HgInitTask extends HgBaseTask { /** * Path to target directory * * @var string */ protected $targetPath; /** * Set path to source repo * * @param string $targetPath Path to repository used as source * * @return void */ public function setTargetPath($targetPath) { $this->targetPath = $targetPath; } /** * Main entry point for this task. * * @return void */ public function main() { $clone = $this->getFactoryInstance('init'); $this->log('Initializing', Project::MSG_INFO); $clone->setQuiet($this->getQuiet()); $clone->setInsecure($this->getInsecure()); $cwd = getcwd(); if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } if (!is_dir($dir)) { throw new BuildException("$dir is not a directory."); } chdir($dir); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg update * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgPullTask.php */ class HgPullTask extends HgBaseTask { /** * Path to target directory * * @var string */ protected $targetPath; /** * Set path to source repo * * @param string $targetPath Path to repository used as source * * @return void */ public function setTargetPath($targetPath) { $this->targetPath = $targetPath; } /** * The main entry point method. * * @throws BuildException * @return void */ public function main() { $clone = $this->getFactoryInstance('pull'); $clone->setInsecure($this->getInsecure()); $clone->setQuiet($this->getQuiet()); $cwd = getcwd(); if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } $this->checkRepositoryIsDirAndExists($dir); chdir($dir); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Base task for integrating phing and mercurial. * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgBaseTask.php */ abstract class HgBaseTask extends Task { /** * Insecure argument * * @var string */ protected $insecure = ''; /** * Repository directory * * @var string */ protected $repository = ''; /** * Whether to be quiet... --quiet argument. * * @var bool */ protected $quiet = false; /** * Username. * * @var string */ protected $user = ''; static $factory = null; /** * Set repository attribute * * @param string $repository Repository * * @return void */ public function setRepository($repository) { $this->repository = $repository; } /** * Set the quiet attribute --quiet * * @param string $quiet yes|no|true|false|1|0 * * @return void */ public function setQuiet($quiet) { $this->quiet = StringHelper::booleanValue($quiet); } /** * Get the quiet attribute value. * * @return bool */ public function getQuiet() { return $this->quiet; } /** * Get Repository attribute/directory. * * @return string */ public function getRepository() { return $this->repository; } /** * Set insecure attribute * * @param string $insecure 'yes', etc. * * @return void */ public function setInsecure($insecure) { $this->insecure = StringHelper::booleanValue($insecure); } /** * Get 'insecure' attribute value. (--insecure or null) * * @return string */ public function getInsecure() { return $this->insecure; } /** * Set user attribute * * @param string $user username/email address. * * @return void */ public function setUser($user) { $this->user = $user; } /** * Get username attribute. * * @return string */ public function getUser() { return $this->user; } /** * Check provided repository directory actually is an existing directory. * * @param string $dir Repository directory * * @return bool * @throws BuildException */ public function checkRepositoryIsDirAndExists($dir) { if (file_exists($dir)) { if (!is_dir($dir)) { throw new BuildException("Repository '$dir' is not a directory."); } } else { throw new BuildException("Repository directory '$dir' does not exist."); } return true; } /** * Initialise the task. * * @return void */ public function init() { if (version_compare(PHP_VERSION, '5.4', "<")) { throw new BuildException('This task requires PHP 5.4+'); } else { /** * Depending on composer for pulling in siad007's VersionControl_HG. */ @include_once 'vendor/autoload.php'; } } public function getFactoryInstance($command, $options = array()) { $vchq = '\\Siad007\\VersionControl\\HG\\Factory'; self::$factory = call_user_func_array( array($vchq, 'getInstance'), array($command, $options) ); return self::$factory; } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg log * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgLogTask.php */ class HgLogTask extends HgBaseTask { /** * Maximum number of changes to get. See --limit * * @var int */ protected $maxCount = null; /** * Commit format/template. See --template * * @var string */ protected $format = null; /** * Revision * * @var string */ protected $revision = ''; /** * Propery name to set the output to. * * @var string */ protected $outputProperty = null; /** * Set maximum number of changes to get. * * @param int $count Maximum number of log entries to retrieve. * * @return void */ public function setMaxcount($count) { $this->maxCount = $count; } /** * Retrieve max count of commits to limit to. * * @return int */ public function getMaxcount() { return $this->maxCount; } /** * Template/log format. * * @param string $format Log format * * @return string */ public function setFormat($format) { $this->format = $format; } /** * Get the log format/template * * @return string */ public function getFormat() { return $this->format; } /** * Property to assign output to. * * @param string $property name of property to assign output to. * * @return void */ public function setOutputProperty($property) { $this->outputProperty = $property; } /** * Set revision attribute * * @param string $revision Revision * * @return void */ public function setRevision($revision) { $this->revision = $revision; } /** * Main entry point for this task * * @return void */ public function main() { $clone = $this->getFactoryInstance('log'); if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } $clone->setCwd($dir); if ($this->maxCount !== null) { $max = filter_var($this->maxCount, FILTER_VALIDATE_INT); if ($max) { $max = (int) $this->maxCount; } if (!$max || (int) $this->maxCount <= 0) { throw new BuildException("maxcount should be a positive integer."); } $clone->setLimit('' . $this->maxCount); } if ($this->format !== null) { $clone->setTemplate($this->format); } if ($this->revision !== '') { $clone->setRev($this->revision); } try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($this->outputProperty !== null) { $this->project->setProperty($this->outputProperty, $output); } else { if ($output !== '') { $this->log(PHP_EOL . $output); } } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } throw new BuildException($msg); } } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg add * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgAddTask.php */ class HgAddTask extends HgBaseTask { /** * Linked filesets * * @var string */ protected $filesets = array(); /** * Array of files to ignore * * @var string[] */ protected $ignoreFile = array(); /** * Adds a fileset of files to add to the repository. * * @param FileSet $fileset Set of files to add to the repository. * * @return void */ public function addFileSet(FileSet $fileset) { $this->filesets[] = $fileset; } /** * The main entry point method. * * @throws BuildException * @return void */ public function main() { $filesAdded = false; $clone = $this->getFactoryInstance('add'); $clone->setQuiet($this->getQuiet()); $cwd = getcwd(); $project = $this->getProject(); if ($this->repository === '') { $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } if (!file_exists($dir)) { throw new BuildException("\"$dir\" does not exist."); } elseif (!is_dir($dir)) { throw new BuildException("\"$dir\" is not a directory."); } chdir($dir); if (file_exists('.hgignore')) { $this->loadIgnoreFile(); } if (count($this->filesets)) { $this->log('filesets set', Project::MSG_DEBUG); /** * $fs is a FileSet * * @var $fs FileSet */ foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($project); $fromDir = $fs->getDir($project); if ($fromDir->getName() === '.') { $statusClone = $this->getFactoryInstance('status'); $statusClone->setUnknown(true); $statusClone->setNoStatus(true); $statusClone->setRepository($this->getRepository()); $statusOut = $statusClone->execute(); if ($statusOut !== '') { $files = explode(PHP_EOL, $statusOut); foreach ($files as $file) { if ($file != '') { $clone->addFile($file); $filesAdded = true; } } } } } } if ($filesAdded) { try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $this->log("Exception: $msg", Project::MSG_INFO); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } } chdir($cwd); } /** * Load .hgignore file. * * @return void */ public function loadIgnoreFile() { $ignores = array(); $lines = file('.hgignore'); foreach ($lines as $line) { $nline = trim($line); $nline = preg_replace('/\/\*$/', '/', $nline); $ignores[] = $nline; } $this->ignoreFile = $ignores; } /** * Determine if a file is to be ignored. * * @param string $file filename * * @return bool */ public function fileIsIgnored($file) { $line = $this->ignoreFile[0]; $mode = 'regexp'; $ignored = false; if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches) || $matches[1] === 'glob' ) { $mode = 'glob'; } if ($mode === 'glob') { $ignored = $this->ignoredByGlob($file); } elseif ($mode === 'regexp') { $ignored = $this->ignoredByRegex($file); } return $ignored; } /** * Determine if file is ignored by glob pattern. * * @param string $file filename * * @return bool */ public function ignoredByGlob($file) { $lfile = $file; if (strpos($lfile, './') === 0) { $lfile = substr($lfile, 2); } foreach ($this->ignoreFile as $line) { if (strpos($lfile, $line) === 0) { return true; } } return false; } /** * Is file ignored by regex? * * @param string $file Filename * * @return bool */ public function ignoredByRegex($file) { return true; } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg clone * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgCloneTask.php */ class HgCloneTask extends HgBaseTask { /** * Path to target directory * * @var string */ protected $targetPath = ''; /** * Set path to source repo * * @param string $targetPath Path to repository used as source * * @return void */ public function setTargetPath($targetPath) { $this->targetPath = $targetPath; } /** * Get path to the target directory/repo. * * @return string */ public function getTargetPath() { return $this->targetPath; } /** * The main entry point. * * @return void * @throws BuildException */ public function main() { $clone = $this->getFactoryInstance('clone'); $repository = $this->getRepository(); if ($repository === '') { throw new BuildException('"repository" is a required parameter'); } $target = $this->getTargetPath(); if ($target === '') { throw new BuildException('"targetPath" is a required parameter'); } // Is target path empty? if (file_exists($target)) { $files = scandir($target); if (is_array($files) && count($files) > 2) { throw new BuildException("Directory \"$target\" is not empty"); } if (!is_dir($target)) { throw new BuildException("\"$target\" is not a directory"); } } $msg = sprintf('hg cloning %s to %s', $repository, $target); $this->log($msg, Project::MSG_INFO); $clone->setSource($repository); $clone->setDestination($target); $clone->setInsecure($this->getInsecure()); $clone->setQuiet($this->getQuiet()); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } throw new BuildException($msg); } } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg push * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgPushTask.php */ class HgPushTask extends HgBaseTask { /** * Whether the task should halt if an error occurs. * * @var bool */ protected $haltonerror = false; /** * Set haltonerror attribute. * * @param string $halt 'yes', or '1' to halt. * * @return void */ public function setHaltonerror($halt) { $this->haltonerror = StringHelper::booleanValue($halt); } /** * Return haltonerror value. * * @return bool */ public function getHaltonerror() { return $this->haltonerror; } /** * The main entry point method. * * @throws BuildException * @return void */ public function main() { $clone = $this->getFactoryInstance('push'); $this->log('Pushing...', Project::MSG_INFO); $clone->setInsecure($this->getInsecure()); $clone->setQuiet($this->getQuiet()); if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } $cwd = getcwd(); $this->checkRepositoryIsDirAndExists($dir); chdir($dir); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); if ($this->haltonerror) { throw new BuildException($msg); } $this->log($msg, Project::MSG_ERR); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg update * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgUpdateTask.php */ class HgUpdateTask extends HgBaseTask { /** * Branch argument * * Defaults to 'default' * * @var string */ protected $branch = 'default'; /** * Clean argument * * @var bool */ protected $clean = false; /** * Set 'clean' attribute. * * @param string $value Clean attribute value * * @return void */ public function setClean($value) { $this->clean = StringHelper::booleanValue($value); } /** * Get 'clean' attribute. * * @return bool */ public function getClean() { return $this->clean; } /** * Set branch attribute * * @param string $value Branch name * * @return void */ public function setBranch($value) { $this->branch = $value; } /** * Get branch attribute * * @return string */ public function getBranch() { return $this->branch; } /** * The main entry point method. * * @throws BuildException * @return void */ public function main() { $pull = $this->getFactoryInstance('update'); try { $pull->setBranch($this->getBranch()); } catch (Exception $ex) { $this->log("Caught: " . $ex->getMessage(), Project::MSG_DEBUG); } $pull->setClean($this->getClean()); $pull->setQuiet($this->getQuiet()); $cwd = getcwd(); if ($this->repository === '') { $prog = $this->getProject(); $dir = $prog->getProperty('application.startdir'); } else { $dir = $this->repository; } $this->checkRepositoryIsDirAndExists($dir); chdir($dir); try { $this->log("Executing: " . $pull->asString(), Project::MSG_INFO); $output = $pull->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg tag * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgTagTask.php */ class HgTagTask extends HgBaseTask { /** * Message to be recorded against tagging. * * @var string */ protected $message = ''; /** * Tag to assign/create. * * @var string */ protected $name = ''; /** * Revision * * @var string */ protected $revision = ''; /** * Set the name argument * * @param string $name Name * * @return void */ public function setName($name) { $this->name = $name; } /** * Get the name of the tag to be used. * * @return void */ public function getName() { return $this->name; } /** * Set message to be used. * * @param string $message Message to use * * @return void */ public function setMessage($message) { $this->message = $message; } /** * Get message to apply for the commit. * * @return string */ public function getMessage() { return $this->message; } /** * Set revision attribute * * @param string $revision Revision * * @return void */ public function setRevision($revision) { $this->revision = $revision; } /** * The main entry point method. * * @return void */ public function main() { $clone = $this->getFactoryInstance('tag'); $cwd = getcwd(); if ($this->name === '') { throw new BuildException("Tag name must be set."); } if ($this->repository === '') { $prog = $this->getProject(); $dir = $prog->getProperty('application.startdir'); } else { $dir = $this->repository; } if ($this->revision !== '') { $clone->setRev($this->revision); } if ($this->user !== null) { $clone->setUser($this->user); } $message = $this->getMessage(); $clone->setMessage($message); $name = $this->getName(); if ($name == '') { throw new BuildException("Name attribute must be set."); } $clone->addName($name); $this->checkRepositoryIsDirAndExists($dir); chdir($dir); try { $this->log("Executing: " . $clone, Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg revert * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgRevertTask.php */ class HgRevertTask extends HgBaseTask { /** * All * * @var bool */ protected $all = false; /** * Name of file to be reverted. * * @var string */ protected $file = null; /** * Revision * * @var string */ protected $revision = ''; /** * Set whether all files are to be reverted. * * @param string $value Jenkins style boolean value * * @return void */ public function setAll($value) { $this->all = StringHelper::booleanValue($value); } /** * Set filename to be reverted. * * @param string $file Filename * * @return void */ public function setFile($file) { $this->file = $file; } /** * Get filename to be reverted. * * @return string */ public function getFile() { return $this->file; } /** * Set revision attribute * * @param string $revision Revision * * @return void */ public function setRevision($revision) { $this->revision = $revision; } /** * The main entry point method. * * @throws BuildException * @return void */ public function main() { $clone = $this->getFactoryInstance('revert'); $clone->setQuiet($this->getQuiet()); $clone->setAll($this->all); if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } $cwd = getcwd(); $this->checkRepositoryIsDirAndExists($dir); chdir($dir); if ($this->revision !== '') { $clone->setRev($this->revision); } if ($this->file !== null) { $clone->addName($this->file); } try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log(PHP_EOL . $output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } throw new BuildException($msg); } } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg commit * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgCommitTask.php */ class HgCommitTask extends HgBaseTask { /** * Message to be recorded against commit. * * @var string */ protected $message = ''; /** * Set message to be used. * * @param string $message Message to use * * @return void */ public function setMessage($message) { $this->message = $message; } /** * Get message to apply for the commit. * * @return string */ public function getMessage() { return $this->message; } /** * The main entry point method. * * @throws BuildException If message is not set * @throws BuildException If error occurs during commit * @return void */ public function main() { $message = $this->getMessage(); if ($message === '') { throw new BuildException('"message" is a required parameter'); } $user = $this->getUser(); $clone = $this->getFactoryInstance('commit'); $msg = sprintf("Commit: '%s'", $message); $this->log($msg, Project::MSG_INFO); $clone->setQuiet($this->getQuiet()); $clone->setMessage($message); if (trim($user) === "") { throw new BuildException('"user" parameter can not be set to ""'); } if ($user !== null) { $clone->setUser($user); $this->log("Commit: user = '$user'", Project::MSG_VERBOSE); } if ($this->repository === '') { $project = $this->getProject(); $dir = $project->getProperty('application.startdir'); } else { $dir = $this->repository; } $this->log('DIR:' . $dir, Project::MSG_INFO); $this->log('REPO: ' . $this->repository, Project::MSG_INFO); $cwd = getcwd(); chdir($dir); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log($output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $this->log("Exception: $msg", Project::MSG_INFO); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } chdir($cwd); throw new BuildException($msg); } chdir($cwd); } } * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link https://github.com/kenguest/Phing-HG */ /** * Pull in Base class. */ require_once 'phing/tasks/ext/hg/HgBaseTask.php'; /** * Integration/Wrapper for hg archive * * @category Tasks * @package phing.tasks.ext.hg * @author Ken Guest * @license LGPL (see http://www.gnu.org/licenses/lgpl.html) * @link HgArchiveTask.php */ class HgArchiveTask extends HgBaseTask { /** * Which revision to archive. * * @var string */ protected $revision = ''; /** * Name of destination archive file. * * @var string */ protected $destination = null; /** * Set revision attribute * * @param string $revision Revision * * @return void */ public function setRevision($revision) { $this->revision = $revision; } /** * Set Destination attribute * * @param string $destination Destination filename * * @return void */ public function setDestination($destination) { $this->destination = $destination; } /** * The main entry point for the task. * * @return void */ public function main() { $clone = $this->getFactoryInstance('archive'); if ($this->revision !== '') { $clone->setRev($this->revision); } if ($this->destination === null) { throw new BuildException("Destination must be set."); } $clone->setDestination($this->destination); try { $this->log("Executing: " . $clone->asString(), Project::MSG_INFO); $output = $clone->execute(); if ($output !== '') { $this->log(PHP_EOL . $output); } } catch(Exception $ex) { $msg = $ex->getMessage(); $p = strpos($msg, 'hg returned:'); if ($p !== false) { $msg = substr($msg, $p + 13); } throw new BuildException($msg); } } } . */ /** * @author Alexey Shockov * @package phing.tasks.ext.phk */ class PhkPackageWebAccessPath { /** * @var string */ private $path; /** * @param string $path */ public function addText($path) { $this->path = trim($path); } /** * @return string */ public function getPath() { return $this->path; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/phk/PhkPackageWebAccess.php'; /** * See {@link http://phk.tekwire.net/} for more information about PHK. * * @author Alexey Shockov * @package phing.tasks.ext.phk */ class PhkPackageTask extends Task { /** * @var string */ private $outputFile; /** * @var string */ private $inputDirectory; /** * @var string */ private $phkCreatorPath; /** * @var PhkPackageWebAccess */ private $webAccess; /** * @var array */ private $modifiers = array(); /** * @var array */ private $options = array(); /** * @return PhkPackageWebAccess */ public function createWebAccess() { return ($this->webAccess = new PhkPackageWebAccess()); } /** * @param string $crcCheck */ public function setCrcCheck($crcCheck) { $this->options['crc_check'] = ('true' == $crcCheck ? true : false); } /** * @param string $webRunScript */ public function setWebRunScript($webRunScript) { $this->options['web_run_script'] = $webRunScript; } /** * @param string $cliRunScript */ public function setCliRunScript($cliRunScript) { $this->options['cli_run_script'] = $cliRunScript; } /** * @param string $libRunScript */ public function setLibRunScript($libRunScript) { $this->options['lib_run_script'] = $libRunScript; } /** * @param string $name */ public function setName($name) { $this->options['name'] = $name; } /** * @param string $webMainRedirect */ public function setWebMainRedirect($webMainRedirect) { $this->options['web_main_redirect'] = ('true' == $webMainRedirect ? true : false); } /** * @param string $pluginClass */ public function setPluginClass($pluginClass) { $this->options['plugin_class'] = $pluginClass; } /** * @param string $version */ public function setVersion($version) { $this->options['version'] = $version; } /** * @param string $summary */ public function setSummary($summary) { $this->options['summary'] = $summary; } /** * @param string $inputDirectory */ public function setInputDirectory($inputDirectory) { $this->inputDirectory = $inputDirectory; } /** * @param string $outputFile */ public function setOutputFile($outputFile) { $this->outputFile = $outputFile; } /** * May be none, gzip or bzip2. * * @param string $compress */ public function setCompress($compress) { $this->modifiers['compress'] = $compress; } /** * True or false. * * @param srting $strip */ public function setStrip($strip) { $this->modifiers['strip'] = $strip; } /** * Path to PHK_Creator.phk file. * * @param srting $path */ public function setPhkCreatorPath($path) { $this->phkCreatorPath = $path; } /** * */ public function init() { } /** * Main method... */ public function main() { /* * Check for empty first - speed ;) */ if (!is_file($this->phkCreatorPath)) { throw new BuildException('You must specify the "phkcreatorpath" attribute for PHK task.'); } if (empty($this->inputDirectory)) { throw new BuildException('You must specify the "inputdirectory" attribute for PHK task.'); } if (empty($this->outputFile)) { throw new BuildException('You must specify the "outputfile" attribute for PHK task.'); } require_once $this->phkCreatorPath; $mountPoint = PHK_Mgr::mount($this->outputFile, PHK::F_CREATOR); $phkManager = PHK_Mgr::instance($mountPoint); /* * Add files. */ $phkManager->ftree()->merge_file_tree('/', $this->inputDirectory, $this->modifiers); /* * Add web_access to options, if present. */ if (!is_null($this->webAccess)) { $webAccessPaths = $this->webAccess->getPaths(); if (!empty($webAccessPaths)) { $this->options['web_access'] = $webAccessPaths; } } $phkManager->set_options($this->options); /* * Intercept output (in PHP we can't intercept stream). */ ob_start(); /* * Create file... */ $phkManager->dump(); /* * Print with Phing log... */ $output = trim(ob_get_clean()); $output = explode("\n", $output); foreach ($output as $line) { /* * Delete all '--- *' lines. Bluh! */ /* * TODO Change preg_math to more faster alternative. */ if (preg_match('/^---/', $line)) { continue; } $this->log($line); } /* * Set rights for generated file... Don't use umask() - see * notes in official documentation for this function. */ chmod($this->outputFile, 0644); } } . */ require_once 'phing/tasks/ext/phk/PhkPackageWebAccessPath.php'; /** * @author Alexey Shockov * @package phing.tasks.ext.phk */ class PhkPackageWebAccess { /** * @var array */ private $paths = array(); /** * @return PhkPackageWebAccessPath */ public function createPath() { return ($this->paths[] = new PhkPackageWebAccessPath()); } /** * @return array */ public function getPaths() { /* * Get real paths... */ $paths = array(); foreach ($this->paths as $path) { $paths[] = $path->getPath(); } return $paths; } } * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the authors nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * PHP version 5 * * @category Tasks * @package phing.tasks.ext * @version $Id: 50d0d2d926e6a51ab78d6801407e90f020dcbad9 $ * @author Laurent Laville * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @link https://github.com/llaville/phing-GrowlNotifyTask */ require_once 'phing/Task.php'; /** * Growl notification task for Phing, the PHP build tool. * * PHP version 5 * * @category Tasks * @package phing.tasks.ext * @version $Id: 50d0d2d926e6a51ab78d6801407e90f020dcbad9 $ * @author Laurent Laville * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @link https://github.com/llaville/phing-GrowlNotifyTask */ class GrowlNotifyTask extends Task { protected $growl; protected $name; protected $sticky; protected $message; protected $title; protected $notification; protected $appicon; protected $host; protected $password; protected $priority; protected $protocol; protected $icon; /** * Initializes task with default options * * @param Net_Growl $growl (optional) mock instance */ public function __construct(Net_Growl $growl = null) { $this->growl = $growl; } /** * The init method check if Net_Growl is available * (exists and can be loaded) * * @return void * @throws BuildException */ public function init() { $autoloader = 'Net/Growl/Autoload.php'; if (!$handle = @fopen($autoloader, 'r', true)) { throw new BuildException( 'The Growl Notify task requires the Net_Growl PEAR package.' ); } else { fclose($handle); include_once $autoloader; } $this->setTaskName('GrowlNotify'); $this->setName(); $this->setSticky(false); $this->setMessage(); $this->setTitle(); $this->setNotification(); $this->setAppicon(); $this->setHost(); $this->setPassword(); $this->setPriority(); $this->setProtocol(); $this->setIcon(); } /** * Defines the name of the application sending the notification * * @param string $name (optional) Name of the application * that appears in your Growl preferences * Default: "Growl for Phing" * * @return void * @throws BuildException */ public function setName($name = '') { if ('' == $name) { $name = 'Growl for Phing'; } if (!is_string($name)) { throw new BuildException( '"name" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($name) ); } $this->name = $name; } /** * Indicates if the notification should be sticky * * @param bool $sticky (optional) Notification should be sticky * * @return void */ public function setSticky($sticky = true) { $this->sticky = (bool) $sticky; } /** * The notification's text is required. * Use \n to specify a line break. * * @param string $message Notification's text * * @return void * @throws BuildException */ public function setMessage($message = '') { if (!is_string($message)) { throw new BuildException( '"message" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($message) ); } $this->message = $message; } /** * The notification's title. * Use \n to specify a line break. * * @param string $title (optional) Notification's title * Default: GrowlNotify * * @return void * @throws BuildException */ public function setTitle($title = '') { if ('' == $title) { $title = 'GrowlNotify'; } if (!is_string($title)) { throw new BuildException( '"title" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($title) ); } $this->title = $title; } /** * The notification name/type * * @param string $notification Name/type * Default: "General Notification" * * @return void * @throws BuildException */ public function setNotification($notification = '') { if ('' == $notification) { $notification = 'General Notification'; } if (!is_string($notification)) { throw new BuildException( '"notification" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($notification) ); } $this->notification = $notification; } /** * The icon of the application being registered. * * Must be a valid file type (png, jpg, gif, ico). * Can be any of the following: * - absolute url (http://domain/image.png) * - absolute file path (c:\temp\image.png) * - relative file path (.\folder\image.png) (relative file paths must start * with a dot and are relative to GrowlNotify's phing task location * * @param string $icon Icon of the application * * @return void * @throws BuildException */ public function setAppicon($icon = '') { if (!is_string($icon)) { throw new BuildException( '"appicon" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($icon) ); } // relative location if (strpos($icon, '..') === 0) { $icon = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . $icon); } elseif (strpos($icon, '.') === 0) { $icon = dirname(__FILE__) . substr($icon, 1); } $this->appicon = $icon; } /** * The host address to send the notification to. * * If any value other than 'localhost' or '127.0.0.1' is provided, the host * is considered a remote host and the "pass" attribute must also be provided. * Default: 127.0.0.1 * * @param string $host Remote host name/ip * Default: 127.0.0.1 * * @return void * @throws BuildException */ public function setHost($host = '127.0.0.1') { if (!is_string($host)) { throw new BuildException( '"host" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($host) ); } $this->host = $host; } /** * The password required to send notifications. * * A password is required to send a request to a remote host. If host attribute * is specified and is any value other than 'localhost' or '127.0.0.1', * then "pass" attribute is also required. * Default: no password * * @param string $password Password to send request to a remote host * * @return void * @throws BuildException */ public function setPassword($password = '') { if (!is_string($password)) { throw new BuildException( '"password" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($password) ); } $this->password = $password; } /** * The notification priority. * * Valid values are : low, moderate, normal, high, emergency * Default: normal * * @param string $priority Notification priority * Default: normal * * @return void * @throws BuildException */ public function setPriority($priority = '') { if ('' == $priority) { $priority = 'normal'; } switch ($priority) { case 'low' : $priority = Net_Growl::PRIORITY_LOW; break; case 'moderate' : $priority = Net_Growl::PRIORITY_MODERATE; break; case 'normal' : $priority = Net_Growl::PRIORITY_NORMAL; break; case 'high' : $priority = Net_Growl::PRIORITY_HIGH; break; case 'emergency' : $priority = Net_Growl::PRIORITY_EMERGENCY; break; default : throw new BuildException( '"priority" attribute is invalid.' ); } $this->priority = $priority; } /** * The protocol (and port) to send the notification to. * * With TCP (GNTP) protocol, port is always 23053 * With UDP protocol, port is always 9887 * Default: 23053 * * @param string $protocol Protocol to use to send request to remote host * Default: gntp * * @return void * @throws BuildException */ public function setProtocol($protocol = '') { if ('' == $protocol) { $protocol = 'gntp'; } switch ($protocol) { case 'udp' : case 'gntp' : break; default : throw new BuildException( '"protocol" attribute is invalid.' . ' Expect to be either udp or gntp.' ); } $this->protocol = $protocol; } /** * The icon to show for the notification. * * Must be a valid file type (png, jpg, gif, ico). * Can be any of the following: * - absolute url (http://domain/image.png) * - absolute file path (c:\temp\image.png) * - relative file path (.\folder\image.png) (relative file paths must start * with a dot and are relative to GrowlNotify's phing task location * * @param string $icon Icon of the message * * @return void * @throws BuildException */ public function setIcon($icon = '') { if (!is_string($icon)) { throw new BuildException( '"icon" attribute is invalid.' . ' Expect to be a string, actual is ' . gettype($icon) ); } // relative location if (strpos($icon, '..') === 0) { $icon = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . $icon); } elseif (strpos($icon, '.') === 0) { $icon = dirname(__FILE__) . substr($icon, 1); } $this->icon = $icon; } /** * The main entry point method * * @return void * @throws BuildException */ public function main() { if (empty($this->message)) { throw new BuildException( '"message" attribute cannot be empty' ); } $notifications = array( $this->notification ); $options = array( 'host' => $this->host, 'protocol' => $this->protocol, ); if (!empty($this->appicon)) { $options['AppIcon'] = $this->appicon; } try { if ($this->growl instanceof Net_Growl) { $growl = $this->growl; } else { $growl = Net_Growl::singleton( $this->name, $notifications, $this->password, $options ); } $response = $growl->register(); if ($this->protocol == 'gntp') { if ($response->getStatus() != 'OK') { throw new BuildException( 'Growl Error ' . $response->getErrorCode() . ' - ' . $response->getErrorDescription() ); } } $this->log( 'Application ' . $this->name . ' registered', Project::MSG_VERBOSE ); $logRequest = array( 'Application-Name' => $this->name, 'Application-Icon' => $this->appicon, 'Notification-Name' => $this->notification, 'Notification-Title' => $this->title, 'Notification-Text' => $this->message, 'Notification-Priority' => $this->priority, 'Notification-Icon' => $this->icon, 'Notification-Sticky' => $this->sticky, ); foreach ($logRequest as $key => $value) { $this->log($key . ': ' . $value, Project::MSG_DEBUG); } $options = array( 'sticky' => $this->sticky, 'priority' => $this->priority, 'icon' => $this->icon, ); $response = $growl->publish( $this->notification, $this->title, $this->message, $options ); if ($this->protocol == 'gntp') { if ($response->getStatus() != 'OK') { throw new BuildException( 'Growl Error ' . $response->getErrorCode() . ' - ' . $response->getErrorDescription() ); } } $this->log('Notification was sent to remote host ' . $this->host); } catch (Net_Growl_Exception $e) { throw new BuildException( 'Growl Exception : ' . $e->getMessage() ); } } } . */ require_once 'phing/system/io/PhingFile.php'; /** * A wrapper for the implementations of PHPMDResultFormatter. * * @package phing.tasks.ext.phpmd * @author Benjamin Schultz * @version $Id: fa23de508582a5bc1d36fab6153d64df333099c6 $ * @since 2.4.1 */ class PHPMDFormatterElement { /** * @var PHPMDResultFormatter */ protected $formatter = null; /** * The type of the formatter. * * @var string */ protected $type = ""; /** * @var string */ protected $className = ""; /** * Whether to use file (or write output to phing log). * * @var boolean */ protected $useFile = true; /** * Output file for formatter. * * @var PhingFile */ protected $outfile = null; /** * Sets the formatter type. * * @param string $type Type of the formatter * * @throws BuildException */ public function setType($type) { $this->type = $type; switch ($this->type) { case 'xml': $this->className = 'XMLRenderer'; break; case 'html': $this->className = 'HTMLRenderer'; break; case 'text': $this->className = 'TextRenderer'; break; default: throw new BuildException('Formatter "' . $this->type . '" not implemented'); } } /** * Get the formatter type * * @return string */ public function getType() { return $this->type; } /** * Set whether to write formatter results to file or not. * * @param boolean $useFile True or false. */ public function setUseFile($useFile) { $this->useFile = StringHelper::booleanValue($useFile); } /** * Return whether to write formatter results to file or not. * * @return boolean */ public function getUseFile() { return $this->useFile; } /** * Sets the output file for the formatter results. * * @param PhingFile $outfile The output file */ public function setOutfile(PhingFile $outfile) { $this->outfile = $outfile; } /** * Get the output file. * * @return PhingFile */ public function getOutfile() { return $this->outfile; } /** * Creates a report renderer instance based on the formatter type. * * @return PHP_PMD_AbstractRenderer * @throws BuildException When the specified renderer does not exist. */ public function getRenderer() { if (!class_exists('\\PHPMD\\Writer\\StreamWriter')) { $renderClass = 'PHP_PMD_RENDERER_' . $this->className; $writerClass = 'PHP_PMD_Writer_Stream'; include_once 'PHP/PMD/Renderer/' . $this->className . '.php'; include_once 'PHP/PMD/Writer/Stream.php'; } else { $renderClass = 'PHPMD\Renderer\\' . $this->className; $writerClass = '\PHPMD\Writer\StreamWriter'; } $renderer = new $renderClass(); // Create a report stream if ($this->getUseFile() === false || $this->getOutfile() === null) { $stream = STDOUT; } else { $stream = fopen($this->getOutfile()->getAbsoluteFile(), 'wb'); } $renderer->setWriter(new $writerClass($stream)); return $renderer; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/phpmd/PHPMDFormatterElement.php'; /** * Runs PHP Mess Detector. Checking PHP files for several potential problems * based on rulesets. * * @package phing.tasks.ext.phpmd * @author Benjamin Schultz * @version $Id: 6de5c80e97545cd52494c53490e96c09aa61e703 $ * @since 2.4.1 */ class PHPMDTask extends Task { /** * A php source code filename or directory * * @var PhingFile */ protected $file = null; /** * All fileset objects assigned to this task * * @var FileSet[] */ protected $filesets = array(); /** * The rule-set filenames or identifier. * * @var string */ protected $rulesets = 'codesize,unusedcode'; /** * The minimum priority for rules to load. * * @var integer */ protected $minimumPriority = 0; /** * List of valid file extensions for analyzed files. * * @var array */ protected $allowedFileExtensions = array('php'); /** * List of exclude directory patterns. * * @var array */ protected $ignorePatterns = array('.git', '.svn', 'CVS', '.bzr', '.hg'); /** * The format for the report * * @var string */ protected $format = 'text'; /** * Formatter elements. * * @var PHPMDFormatterElement[] */ protected $formatters = array(); /** * @var bool */ protected $newVersion = true; /** * @var string */ protected $pharLocation = ""; /** * Cache data storage * * @var DataStore */ protected $cache; /** * Set the input source file or directory. * * @param PhingFile $file The input source file or directory. */ public function setFile(PhingFile $file) { $this->file = $file; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * Sets the minimum rule priority. * * @param integer $minimumPriority Minimum rule priority. */ public function setMinimumPriority($minimumPriority) { $this->minimumPriority = $minimumPriority; } /** * Sets the rule-sets. * * @param string $ruleSetFileNames Comma-separated string of rule-set filenames or identifier. */ public function setRulesets($ruleSetFileNames) { $this->rulesets = $ruleSetFileNames; } /** * Sets a list of filename extensions for valid php source code files. * * @param string $fileExtensions List of valid file extensions without leading dot. */ public function setAllowedFileExtensions($fileExtensions) { $this->allowedFileExtensions = array(); $token = ' ,;'; $ext = strtok($fileExtensions, $token); while ($ext !== false) { $this->allowedFileExtensions[] = $ext; $ext = strtok($token); } } /** * Sets a list of ignore patterns that is used to exclude directories from the source analysis. * * @param string $ignorePatterns List of ignore patterns. */ public function setIgnorePatterns($ignorePatterns) { $this->ignorePatterns = array(); $token = ' ,;'; $pattern = strtok($ignorePatterns, $token); while ($pattern !== false) { $this->ignorePatterns[] = $pattern; $pattern = strtok($token); } } /** * Create object for nested formatter element. * * @return PHPMDFormatterElement */ public function createFormatter() { $num = array_push($this->formatters, new PHPMDFormatterElement()); return $this->formatters[$num - 1]; } /** * @param string $format */ public function setFormat($format) { $this->format = $format; } /** * @param string $pharLocation */ public function setPharLocation($pharLocation) { $this->pharLocation = $pharLocation; } /** * Whether to store last-modified times in cache * * @param PhingFile $file */ public function setCacheFile(PhingFile $file) { $this->cache = new DataStore($file); } /** * Find PHPMD * * @return string * @throws BuildException */ protected function loadDependencies() { if (!empty($this->pharLocation)) { include_once 'phar://' . $this->pharLocation . '/vendor/autoload.php'; } $className = '\PHPMD\PHPMD'; if (!class_exists($className)) { @include_once 'PHP/PMD.php'; $className = "PHP_PMD"; $this->newVersion = false; } if (!class_exists($className)) { throw new BuildException( 'PHPMDTask depends on PHPMD being installed and on include_path or listed in pharLocation.', $this->getLocation() ); } if ($this->newVersion) { //weird syntax to allow 5.2 parser compatibility $minPriority = constant('\PHPMD\AbstractRule::LOWEST_PRIORITY'); require_once 'phing/tasks/ext/phpmd/PHPMDRendererRemoveFromCache.php'; } else { require_once 'PHP/PMD/AbstractRule.php'; $minPriority = PHP_PMD_AbstractRule::LOWEST_PRIORITY; } if (!$this->minimumPriority) { $this->minimumPriority = $minPriority; } return $className; } /** * Return the list of files to parse * * @return string[] list of absolute files to parse */ protected function getFilesToParse() { $filesToParse = array(); if ($this->file instanceof PhingFile) { $filesToParse[] = $this->file->getPath(); } else { // append any files in filesets foreach ($this->filesets as $fs) { $dir = $fs->getDir($this->project)->getAbsolutePath(); foreach ($fs->getDirectoryScanner($this->project)->getIncludedFiles() as $filename) { $fileAbsolutePath = $dir . DIRECTORY_SEPARATOR . $filename; if ($this->cache) { $lastMTime = $this->cache->get($fileAbsolutePath); $currentMTime = filemtime($fileAbsolutePath); if ($lastMTime >= $currentMTime) { continue; } else { $this->cache->put($fileAbsolutePath, $currentMTime); } } $filesToParse[] = $fileAbsolutePath; } } } return $filesToParse; } /** * Executes PHPMD against PhingFile or a FileSet * * @throws BuildException - if the phpmd classes can't be loaded. */ public function main() { $className = $this->loadDependencies(); if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException('Missing either a nested fileset or attribute "file" set'); } if (count($this->formatters) == 0) { // turn legacy format attribute into formatter $fmt = new PHPMDFormatterElement(); $fmt->setType($this->format); $fmt->setUseFile(false); $this->formatters[] = $fmt; } $reportRenderers = array(); foreach ($this->formatters as $fe) { if ($fe->getType() == '') { throw new BuildException('Formatter missing required "type" attribute.'); } if ($fe->getUsefile() && $fe->getOutfile() === null) { throw new BuildException('Formatter requires "outfile" attribute when "useFile" is true.'); } $reportRenderers[] = $fe->getRenderer(); } if ($this->newVersion && $this->cache) { $reportRenderers[] = new PHPMDRendererRemoveFromCache($this->cache); } else { $this->cache = null; // cache not compatible to old version } // Create a rule set factory if ($this->newVersion) { $ruleSetClass = '\PHPMD\RuleSetFactory'; $ruleSetFactory = new $ruleSetClass(); //php 5.2 parser compatibility } else { if (!class_exists("PHP_PMD_RuleSetFactory")) { @include 'PHP/PMD/RuleSetFactory.php'; } $ruleSetFactory = new PHP_PMD_RuleSetFactory(); } $ruleSetFactory->setMinimumPriority($this->minimumPriority); /** * @var PHPMD\PHPMD $phpmd */ $phpmd = new $className(); $phpmd->setFileExtensions($this->allowedFileExtensions); $phpmd->setIgnorePattern($this->ignorePatterns); $filesToParse = $this->getFilesToParse(); if (count($filesToParse) > 0) { $inputPath = implode(',', $filesToParse); $this->log('Processing files...'); $phpmd->processFiles($inputPath, $this->rulesets, $reportRenderers, $ruleSetFactory); if ($this->cache) { $this->cache->commit(); } $this->log('Finished processing files'); } else { $this->log('No files to process'); } } } . */ require_once 'phing/util/DataStore.php'; use PHPMD\AbstractRenderer; use PHPMD\Report; /** * This class will remove files with violations from cache * * @category PHP * @package PHPMD * @author Rui Filipe Da Cunha Alves */ class PHPMDRendererRemoveFromCache extends AbstractRenderer { /** * Cache data storage * @var DataStore */ protected $cache; /** * Constructor * * @param DataStore $cache */ public function __construct($cache) { $this->cache = $cache; } /** * This method will be called when the engine has finished the source * analysis phase. To remove file with violations from cache. * * @param Report $report * @return void */ public function renderReport(Report $report) { foreach ($report->getRuleViolations() as $violation) { $fileName = $violation->getFileName(); $this->cache->remove($fileName, null); } } } . */ require_once 'phing/system/io/PhingFile.php'; /** * Analyzer element for the PhpDependTask * * @package phing.tasks.ext.pdepend * @author Benjamin Schultz * @version $Id: e97cb62953c381f62ab548dfe073b26071f0eb0a $ * @since 2.4.1 */ class PhpDependAnalyzerElement { /** * The type of the analyzer * * @var string */ protected $type = ''; /** * The value(s) for the analyzer option * * @var array */ protected $value = array(); /** * Sets the analyzer type * * @param string $type Type of the analyzer * * @throws BuildException */ public function setType($type) { $this->type = $type; switch ($this->type) { case 'coderank-mode': break; default: throw new BuildException('Analyzer "' . $this->type . '" not implemented'); } } /** * Get the analyzer type * * @return string */ public function getType() { return $this->type; } /** * Sets the value for the analyzer * * @param string $value Value for the analyzer */ public function setValue($value) { $this->value = array(); $token = ' ,;'; $values = strtok($value, $token); while ($values !== false) { $this->value[] = $values; $values = strtok($token); } } /** * Get the analyzer value * * @return string */ public function getValue() { return $this->value; } } . */ require_once 'phing/system/io/PhingFile.php'; /** * Logger element for the PhpDependTask. * * @package phing.tasks.ext.pdepend * @author Benjamin Schultz * @version $Id: c5b569118db6a6d66c6568702f14e8ae37fad9a3 $ * @since 2.4.1 */ class PhpDependLoggerElement { /** * The type of the logger. * * @var string */ protected $type = ''; /** * Output file for logger. * * @var PhingFile */ protected $outfile = null; /** * Sets the logger type. * * @param string $type Type of the logger * * @throws BuildException */ public function setType($type) { $this->type = $type; switch ($this->type) { case 'jdepend-chart': case 'jdepend-xml': case 'overview-pyramid': case 'phpunit-xml': case 'summary-xml': break; default: throw new BuildException('Logger "' . $this->type . '" not implemented'); } } /** * Get the logger type * * @return string */ public function getType() { return $this->type; } /** * Sets the output file for the logger results. * * @param PhingFile $outfile The output file */ public function setOutfile(PhingFile $outfile) { $this->outfile = $outfile; } /** * Get the output file. * * @return PhingFile */ public function getOutfile() { return $this->outfile; } } . */ require_once 'phing/Task.php'; require_once 'phing/tasks/ext/pdepend/PhpDependLoggerElement.php'; require_once 'phing/tasks/ext/pdepend/PhpDependAnalyzerElement.php'; /** * Runs the PHP_Depend software analyzer and metric tool. * Performs static code analysis on a given source base. * * @package phing.tasks.ext.pdepend * @author Benjamin Schultz * @version $Id: 7ef44b418426e61cb1ea3b8cf87b289d79f663aa $ * @since 2.4.1 */ class PhpDependTask extends Task { /** * A php source code filename or directory * * @var PhingFile */ protected $file = null; /** * All fileset objects assigned to this task * * @var FileSet[] */ protected $filesets = array(); /** * List of allowed file extensions. Default file extensions are php * and

php5. * * @var array */ protected $allowedFileExtensions = array('php', 'php5'); /** * List of exclude directories. Default exclude dirs are .git, * .svn and CVS. * * @var array */ protected $excludeDirectories = array('.git', '.svn', 'CVS'); /** * List of exclude packages * * @var array */ protected $excludePackages = array(); /** * Should the parse ignore doc comment annotations? * * @var boolean */ protected $withoutAnnotations = false; /** * Should PHP_Depend treat +global as a regular project package? * * @var boolean */ protected $supportBadDocumentation = false; /** * Flag for enable/disable debugging * * @var boolean */ protected $debug = false; /** * PHP_Depend configuration file * * @var PhingFile */ protected $configFile = null; /** * Logger elements * * @var PhpDependLoggerElement[] */ protected $loggers = array(); /** * Analyzer elements * * @var PhpDependAnalyzerElement[] */ protected $analyzers = array(); /** * Holds the PHP_Depend runner instance * * @var PHP_Depend_TextUI_Runner */ protected $runner = null; /** * Flag that determines whether to halt on error * * @var boolean */ protected $haltonerror = false; /** * @var bool */ private $oldVersion = false; /** * @var string */ protected $pharLocation = ""; /** * Load the necessary environment for running PHP_Depend * * @throws BuildException */ protected function requireDependencies() { if (!empty($this->pharLocation)) { include_once 'phar://' . $this->pharLocation . '/vendor/autoload.php'; } // check 2.x version (composer/phar) if (class_exists('PDepend\\TextUI\\Runner')) { return; } $this->oldVersion = true; // check 1.x version (composer) if (class_exists('PHP_Depend_TextUI_Runner')) { // include_path hack for PHP_Depend 1.1.3 $rc = new ReflectionClass('PHP_Depend'); set_include_path(get_include_path() . ":" . realpath(dirname($rc->getFileName()) . "/../")); return; } @include_once 'PHP/Depend/Autoload.php'; if (!class_exists('PHP_Depend_Autoload')) { throw new BuildException( 'PhpDependTask depends on PHP_Depend being installed and on include_path', $this->getLocation() ); } // register PHP_Depend autoloader $autoload = new PHP_Depend_Autoload(); $autoload->register(); } /** * Set the input source file or directory * * @param PhingFile $file The input source file or directory */ public function setFile(PhingFile $file) { $this->file = $file; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * Sets a list of filename extensions for valid php source code files * * @param string $fileExtensions List of valid file extensions */ public function setAllowedFileExtensions($fileExtensions) { $this->allowedFileExtensions = array(); $token = ' ,;'; $ext = strtok($fileExtensions, $token); while ($ext !== false) { $this->allowedFileExtensions[] = $ext; $ext = strtok($token); } } /** * Sets a list of exclude directories * * @param string $excludeDirectories List of exclude directories */ public function setExcludeDirectories($excludeDirectories) { $this->excludeDirectories = array(); $token = ' ,;'; $pattern = strtok($excludeDirectories, $token); while ($pattern !== false) { $this->excludeDirectories[] = $pattern; $pattern = strtok($token); } } /** * Sets a list of exclude packages * * @param string $excludePackages Exclude packages */ public function setExcludePackages($excludePackages) { $this->excludePackages = array(); $token = ' ,;'; $pattern = strtok($excludePackages, $token); while ($pattern !== false) { $this->excludePackages[] = $pattern; $pattern = strtok($token); } } /** * Should the parser ignore doc comment annotations? * * @param boolean $withoutAnnotations */ public function setWithoutAnnotations($withoutAnnotations) { $this->withoutAnnotations = StringHelper::booleanValue($withoutAnnotations); } /** * Should PHP_Depend support projects with a bad documentation. If this * option is set to true, PHP_Depend will treat the default package * +global as a regular project package. * * @param boolean $supportBadDocumentation */ public function setSupportBadDocumentation($supportBadDocumentation) { $this->supportBadDocumentation = StringHelper::booleanValue($supportBadDocumentation); } /** * Set debugging On/Off * * @param boolean $debug */ public function setDebug($debug) { $this->debug = StringHelper::booleanValue($debug); } /** * Set halt on error * * @param boolean $haltonerror */ public function setHaltonerror($haltonerror) { $this->haltonerror = StringHelper::booleanValue($haltonerror); } /** * Set the configuration file * * @param PhingFile $configFile The configuration file */ public function setConfigFile(PhingFile $configFile) { $this->configFile = $configFile; } /** * Create object for nested logger element * * @return PhpDependLoggerElement */ public function createLogger() { $num = array_push($this->loggers, new PhpDependLoggerElement()); return $this->loggers[$num - 1]; } /** * Create object for nested analyzer element * * @return PhpDependAnalyzerElement */ public function createAnalyzer() { $num = array_push($this->analyzers, new PhpDependAnalyzerElement()); return $this->analyzers[$num - 1]; } /** * @param string $pharLocation */ public function setPharLocation($pharLocation) { $this->pharLocation = $pharLocation; } /** * Executes PHP_Depend_TextUI_Runner against PhingFile or a FileSet * * @throws BuildException */ public function main() { $this->requireDependencies(); if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException('Missing either a nested fileset or attribute "file" set'); } if (count($this->loggers) == 0) { throw new BuildException('Missing nested "logger" element'); } $this->validateLoggers(); $this->validateAnalyzers(); $filesToParse = $this->getFilesToParse(); $runner = $this->createRunner(); $runner->setSourceArguments($filesToParse); foreach ($this->loggers as $logger) { // Register logger if ($this->oldVersion) { $runner->addLogger( $logger->getType(), $logger->getOutfile()->__toString() ); } else { $runner->addReportGenerator( $logger->getType(), $logger->getOutfile()->__toString() ); } } foreach ($this->analyzers as $analyzer) { // Register additional analyzer $runner->addOption( $analyzer->getType(), $analyzer->getValue() ); } // Disable annotation parsing if ($this->withoutAnnotations) { $runner->setWithoutAnnotations(); } // Enable bad documentation support if ($this->supportBadDocumentation) { $runner->setSupportBadDocumentation(); } // Check for suffix if (count($this->allowedFileExtensions) > 0) { $runner->setFileExtensions($this->allowedFileExtensions); } // Check for ignore directories if (count($this->excludeDirectories) > 0) { $runner->setExcludeDirectories($this->excludeDirectories); } // Check for exclude packages if (count($this->excludePackages) > 0) { $runner->setExcludePackages($this->excludePackages); } $runner->run(); if ($runner->hasParseErrors() === true) { $this->log('Following errors occurred:'); foreach ($runner->getParseErrors() as $error) { $this->log($error); } if ($this->haltonerror === true) { throw new BuildException('Errors occurred during parse process'); } } } /** * Validates the available loggers * * @throws BuildException */ protected function validateLoggers() { foreach ($this->loggers as $logger) { if ($logger->getType() === '') { throw new BuildException('Logger missing required "type" attribute'); } if ($logger->getOutfile() === null) { throw new BuildException('Logger requires "outfile" attribute'); } } } /** * Validates the available analyzers * * @throws BuildException */ protected function validateAnalyzers() { foreach ($this->analyzers as $analyzer) { if ($analyzer->getType() === '') { throw new BuildException('Analyzer missing required "type" attribute'); } if (count($analyzer->getValue()) === 0) { throw new BuildException('Analyzer missing required "value" attribute'); } } } /** * @return array */ private function getFilesToParse() { $filesToParse = array(); if ($this->file instanceof PhingFile) { $filesToParse[] = $this->file->__toString(); return $filesToParse; } else { // append any files in filesets foreach ($this->filesets as $fs) { $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles(); foreach ($files as $filename) { $f = new PhingFile($fs->getDir($this->project), $filename); $filesToParse[] = $f->getAbsolutePath(); } } return $filesToParse; } } /** * @return object */ private function createRunner() { if ($this->oldVersion) { return $this->createLegacyRunner(); } $applicationClassName = 'PDepend\\Application'; $application = new $applicationClassName(); $runner = $application->getRunner(); $configuration = $this->getConfiguration(); if ($configuration === null) { $configuration = $application->getConfiguration(); } if ($this->debug) { // Enable debug logging call_user_func('PDepend\\Util\\Log::setSeverity', 1); } call_user_func('PDepend\\Util\\ConfigurationInstance::set', $configuration); return $runner; } /** * @return PHP_Depend_TextUI_Runner */ private function createLegacyRunner() { $runner = new PHP_Depend_TextUI_Runner(); $runner->addProcessListener(new PHP_Depend_TextUI_ResultPrinter()); if ($this->debug) { require_once 'PHP/Depend/Util/Log.php'; // Enable debug logging PHP_Depend_Util_Log::setSeverity(PHP_Depend_Util_Log::DEBUG); } $configuration = $this->getConfiguration(); if ($configuration === null) { $configurationFactory = new PHP_Depend_Util_Configuration_Factory(); $configuration = $configurationFactory->createDefault(); } PHP_Depend_Util_ConfigurationInstance::set($configuration); $runner->setConfiguration($configuration); return $runner; } /** * Loads configuration file * @return null|PHP_Depend_Util_Configuration * @throws BuildException */ private function getConfiguration() { // Check for configuration option if ($this->configFile == null || ! ($this->configFile instanceof PhingFile)) { return null; } if (file_exists($this->configFile->__toString()) === false) { throw new BuildException( 'The configuration file "' . $this->configFile->__toString() . '" doesn\'t exist.' ); } if ($this->oldVersion) { $configurationClassName = 'PHP_Depend_Util_Configuration'; } else { $configurationClassName = 'PDepend\\Util\\Configuration'; } return new $configurationClassName( $this->configFile->__toString(), null, true ); } } . */ include_once 'phing/Task.php'; include_once 'phing/BuildException.php'; include_once 'phing/lib/Capsule.php'; include_once 'phing/util/StringHelper.php'; /** * A phing task for generating output by using Capsule. * * This is based on the interface to TexenTask from Apache's Velocity engine. * * @author Hans Lellelid * * @package phing.tasks.ext */ class CapsuleTask extends Task { /** * Capsule "template" engine. * @var Capsule */ protected $context; /** * Any vars assigned via the build file. * @var array AssignedVar[] */ protected $assignedVars = array(); /** * This is the control template that governs the output. * It may or may not invoke the services of worker * templates. * @var string */ protected $controlTemplate; /** * This is where Velocity will look for templates * using the file template loader. * @var string */ protected $templatePath; /** * This is where texen will place all the output * that is a product of the generation process. * @var string */ protected $outputDirectory; /** * This is the file where the generated text * will be placed. * @var string */ protected $outputFile; /** *

* These are properties that are fed into the * initial context from a properties file. This * is simply a convenient way to set some values * that you wish to make available in the context. *

*

* These values are not critical, like the template path * or output path, but allow a convenient way to * set a value that may be specific to a particular * generation task. *

*

* For example, if you are generating scripts to allow * user to automatically create a database, then * you might want the $databaseName * to be placed * in the initial context so that it is available * in a script that might look something like the * following: *

     * #!bin/sh
     *
     * echo y | mysqladmin create $databaseName
     * 
* The value of $databaseName isn't critical to * output, and you obviously don't want to change * the ant task to simply take a database name. * So initial context values can be set with * properties file. * * @var array */ protected $contextProperties; // ----------------------------------------------------------------------- // The following getters & setters are used by phing to set properties // specified in the XML for the capsule task. // ----------------------------------------------------------------------- /** * [REQUIRED] Set the control template for the * generating process. * @param string $controlTemplate * @return void */ public function setControlTemplate($controlTemplate) { $this->controlTemplate = $controlTemplate; } /** * Get the control template for the * generating process. * @return string */ public function getControlTemplate() { return $this->controlTemplate; } /** * [REQUIRED] Set the path where Velocity will look * for templates using the file template * loader. * @param $templatePath * @return void */ public function setTemplatePath($templatePath) { $resolvedPath = ""; $tok = strtok($templatePath, ","); while ($tok) { // resolve relative path from basedir and leave // absolute path untouched. $fullPath = $this->project->resolveFile($tok); $cpath = $fullPath->getCanonicalPath(); if ($cpath === false) { $this->log("Template directory does not exist: " . $fullPath->getAbsolutePath()); } else { $resolvedPath .= $cpath; } $tok = strtok(","); if ($tok) { $resolvedPath .= ","; } } $this->templatePath = $resolvedPath; } /** * Get the path where Velocity will look * for templates using the file template * loader. * @return string */ public function getTemplatePath() { return $this->templatePath; } /** * [REQUIRED] Set the output directory. It will be * created if it doesn't exist. * @param PhingFile $outputDirectory * @return void * @throws Exception */ public function setOutputDirectory(PhingFile $outputDirectory) { try { if (!$outputDirectory->exists()) { $this->log( "Output directory does not exist, creating: " . $outputDirectory->getPath(), Project::MSG_VERBOSE ); if (!$outputDirectory->mkdirs()) { throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath()); } } $this->outputDirectory = $outputDirectory->getCanonicalPath(); } catch (IOException $ioe) { throw new BuildException($ioe); } } /** * Get the output directory. * @return string */ public function getOutputDirectory() { return $this->outputDirectory; } /** * [REQUIRED] Set the output file for the * generation process. * @param string $outputFile (TODO: change this to File) * @return void */ public function setOutputFile($outputFile) { $this->outputFile = $outputFile; } /** * Get the output file for the * generation process. * @return string */ public function getOutputFile() { return $this->outputFile; } /** * Set the context properties that will be * fed into the initial context be the * generating process starts. * @param string $file * @throws BuildException * @return void */ public function setContextProperties($file) { $sources = explode(",", $file); $this->contextProperties = new Properties(); // Always try to get the context properties resource // from a file first. Templates may be taken from a JAR // file but the context properties resource may be a // resource in the filesystem. If this fails than attempt // to get the context properties resource from the // classpath. for ($i = 0, $sourcesLength = count($sources); $i < $sourcesLength; $i++) { $source = new Properties(); try { // resolve relative path from basedir and leave // absolute path untouched. $fullPath = $this->project->resolveFile($sources[$i]); $this->log("Using contextProperties file: " . $fullPath->toString()); $source->load($fullPath); } catch (Exception $e) { throw new BuildException("Context properties file " . $sources[$i] . " could not be found in the file system!"); } $keys = $source->keys(); foreach ($keys as $key) { $name = $key; $value = $this->project->replaceProperties($source->getProperty($name)); $this->contextProperties->setProperty($name, $value); } } } /** * Get the context properties that will be * fed into the initial context be the * generating process starts. * @return Properties */ public function getContextProperties() { return $this->contextProperties; } /** * Creates an "AssignedVar" class. */ public function createAssign() { $a = new AssignedVar(); $this->assignedVars[] = $a; return $a; } // --------------------------------------------------------------- // End of XML setters & getters // --------------------------------------------------------------- /** * Creates a Smarty object. * * @return Capsule initialized (cleared) Smarty context. * @throws Exception the execute method will catch * and rethrow as a BuildException */ public function initControlContext() { $this->context->clear(); foreach ($this->assignedVars as $var) { $this->context->put($var->getName(), $var->getValue()); } return $this->context; } /** * Execute the input script with Velocity * * @throws BuildException * BuildExceptions are thrown when required attributes are missing. * Exceptions thrown by Velocity are rethrown as BuildExceptions. */ public function main() { // Make sure the template path is set. if (empty($this->templatePath)) { throw new BuildException("The template path needs to be defined!"); } // Make sure the control template is set. if ($this->controlTemplate === null) { throw new BuildException("The control template needs to be defined!"); } // Make sure the output directory is set. if ($this->outputDirectory === null) { throw new BuildException("The output directory needs to be defined!"); } // Make sure there is an output file. if ($this->outputFile === null) { throw new BuildException("The output file needs to be defined!"); } // Setup Smarty runtime. // Smarty uses one object to store properties and to store // the context for the template (unlike Velocity). We setup this object, calling it // $this->context, and then initControlContext simply zeros out // any assigned variables. $this->context = new Capsule(); if ($this->templatePath !== null) { $this->log("Using templatePath: " . $this->templatePath); $this->context->setTemplatePath($this->templatePath); } // Make sure the output directory exists, if it doesn't // then create it. $outputDir = new PhingFile($this->outputDirectory); if (!$outputDir->exists()) { $this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath()); $outputDir->mkdirs(); } $this->context->setOutputDirectory($outputDir->getAbsolutePath()); $path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile; $this->log("Generating to file " . $path); //$writer = new FileWriter($path); // The generator and the output path should // be placed in the init context here and // not in the generator class itself. $c = $this->initControlContext(); // Set any variables that need to always // be loaded $this->populateInitialContext($c); // Feed all the options into the initial // control context so they are available // in the control/worker templates. if ($this->contextProperties !== null) { foreach ($this->contextProperties->keys() as $property) { $value = $this->contextProperties->getProperty($property); // Special exception (from Texen) // for properties ending in file.contents: // in that case we dump the contents of the file // as the "value" for the Property. if (preg_match('/file\.contents$/', $property)) { // pull in contents of file specified $property = substr($property, 0, strpos($property, "file.contents") - 1); // reset value, and then // read in the contents of the file into that var $value = ""; $f = new PhingFile($this->project->resolveFile($value)->getCanonicalPath()); if ($f->exists()) { $fr = new FileReader($f); $fr->readInto($value); } } // if ends with file.contents if (StringHelper::isBoolean($value)) { $value = StringHelper::booleanValue($value); } $c->put($property, $value); } // foreach property } // if contextProperties !== null try { $this->log("Parsing control template: " . $this->controlTemplate); $c->parse($this->controlTemplate, $path); } catch (Exception $ioe) { throw new BuildException("Cannot write parsed template: " . $ioe->getMessage()); } $this->cleanup(); } /** * Place useful objects into the initial context. * * * @param Capsule $context The context to populate, as retrieved from * {@link #initControlContext()}. * @return void * @throws Exception Error while populating context. The {@link * #main()} method will catch and rethrow as a * BuildException. */ protected function populateInitialContext(Capsule $context) { $this->context->put("now", strftime("%c", time())); $this->context->put("task", $this); } /** * A hook method called at the end of {@link #execute()} which can * be overridden to perform any necessary cleanup activities (such * as the release of database connections, etc.). By default, * does nothing. * * @return void */ protected function cleanup() { } } /** * An "inner" class for holding assigned var values. * May be need to expand beyond name/value in the future. * * @package phing.tasks.ext */ class AssignedVar { private $name; private $value; /** * @param string $v */ public function setName($v) { $this->name = $v; } /** * @param mixed $v */ public function setValue($v) { $this->value = $v; } /** * @return string */ public function getName() { return $this->name; } /** * @return mixed */ public function getValue() { return $this->value; } } . */ /** * A property element nested in SonarTask. * * @author Bernhard Mendl * @package phing.tasks.ext.sonar */ class SonarProperty { /** * * @var string */ private $name; /** * * @var string */ private $value; /** * * @return string */ public function getName() { return $this->name; } /** * * @param string $name * @return void */ public function setName($name) { $this->name = (string) $name; } /** * * @return string */ public function getValue() { return $this->value; } /** * * @param string $value * @return void */ public function setValue($value) { $this->value = (string) $value; } } . */ require_once 'phing/BuildException.php'; require_once 'phing/Project.php'; require_once 'phing/Task.php'; require_once 'phing/tasks/ext/sonar/SonarConfigurationFileParser.php'; require_once 'phing/tasks/ext/sonar/SonarProperty.php'; /** * Runs SonarQube Scanner. * * @author Bernhard Mendl * @package phing.tasks.ext.sonar * @see http://www.sonarqube.org */ class SonarTask extends Task { const EXIT_SUCCESS = 0; /** * * @var string|null */ private $executable = null; /** * * @var string */ private $errors = 'false'; /** * * @var string */ private $debug = 'false'; /** * * @var string|null */ private $configuration = null; /** * * @var array Nested *Property* elements. * @see Property */ private $propertyElements = array(); /** * The command-line options passed to the SonarQube Scanner executable. * * @var array */ private $commandLineOptions = array(); /** * Map containing SonarQube's "analysis parameters". * * Map keys are SonarQube parameter names. Map values are parameter values. * See {@link http://docs.sonarqube.org/display/SONAR/Analysis+Parameters}. * * @var array */ private $properties = array(); /** * Sets the path of the SonarQube Scanner executable. * * If the SonarQube Scanner is included in the PATH environment variable, * the file name is sufficient. * * @param string $executable * @return void */ public function setExecutable($executable) { $this->executable = (string) $executable; $message = sprintf("Set executable to [%s].", $this->executable); $this->log($message, Project::MSG_DEBUG); } /** * Sets or unsets the "--errors" flag of SonarQube Scanner. * * @param string $errors * Allowed values are "true"/"false", "yes"/"no", or "1"/"0". * @return void */ public function setErrors($errors) { $this->errors = strtolower((string) $errors); $message = sprintf("Set errors flag to [%s].", $this->errors); $this->log($message, Project::MSG_DEBUG); } /** * Sets or unsets the "--debug" flag of SonarQube Scanner. * * @param string $debug * Allowed values are "true"/"false", "yes"/"no", or "1"/"0". * @return void */ public function setDebug($debug) { $this->debug = strtolower((string) $debug); $message = sprintf("Set debug flag to [%s].", $this->debug); $this->log($message, Project::MSG_DEBUG); } /** * Sets the path of a configuration file for SonarQube Scanner. * * @param string $configuration * @return void */ public function setConfiguration($configuration) { $this->configuration = (string) $configuration; $message = sprintf("Set configuration to [%s].", $this->configuration); $this->log($message, Project::MSG_DEBUG); } /** * Adds a nested Property element. * * @param SonarProperty $property * @return void */ public function addProperty(SonarProperty $property) { $this->propertyElements[] = $property; $message = sprintf("Added property: [%s] = [%s].", $property->getName(), $property->getValue()); $this->log($message, Project::MSG_DEBUG); } /** * * {@inheritdoc} * * @see Task::init() */ public function init() { $this->checkExecAllowed(); } /** * * {@inheritdoc} * * @see Task::main() */ public function main() { $this->validateErrors(); $this->validateDebug(); $this->validateConfiguration(); $this->validateProperties(); $this->validateExecutable(); $command = sprintf('%s %s', escapeshellcmd($this->executable), $this->constructOptionsString()); $message = sprintf('Executing: [%s]', $command); $this->log($message, Project::MSG_VERBOSE); exec($command, $output, $returnCode); foreach ($output as $line) { $this->log($line); } if ($returnCode !== self::EXIT_SUCCESS) { throw new BuildException('Execution of SonarQube Scanner failed.'); } } /** * Constructs command-line options string for SonarQube Scanner. * * @return string */ private function constructOptionsString() { $options = implode(' ', $this->commandLineOptions); foreach ($this->properties as $name => $value) { $arg = sprintf('%s=%s', $name, $value); $options .= ' -D ' . escapeshellarg($arg); } return $options; } /** * Check whether PHP function 'exec()' is available. * * @throws BuildException * @return void */ private function checkExecAllowed() { if (! function_exists('exec') || ! is_callable('exec')) { $message = 'Cannot execute SonarQube Scanner because calling PHP function exec() is not permitted by PHP configuration.'; throw new BuildException($message); } } /** * * @throws BuildException * @return void */ private function validateExecutable() { if (($this->executable === null) || ($this->executable === '')) { $message = 'You must specify the path of the SonarQube Scanner using the "executable" attribute.'; throw new BuildException($message); } // Note that executable is used as argument here. $escapedExecutable = escapeshellarg($this->executable); if ($this->isWindows()) { $message = 'Assuming a Windows system. Looking for SonarQube Scanner ...'; $command = 'where ' . $escapedExecutable; } else { $message = 'Assuming a Linux or Mac system. Looking for SonarQube Scanner ...'; $command = 'which ' . $escapedExecutable; } $this->log($message, Project::MSG_VERBOSE); unset($output); exec($command, $output, $returnCode); if ($returnCode !== self::EXIT_SUCCESS) { $message = sprintf('Cannot find SonarQube Scanner: [%s].', $this->executable); throw new BuildException($message); } // Verify that executable is indeed SonarQube Scanner ... $escapedExecutable = escapeshellcmd($this->executable); unset($output); exec($escapedExecutable . ' --version', $output, $returnCode); if ($returnCode !== self::EXIT_SUCCESS) { $message = sprintf('Could not check version string. Executable appears not to be SonarQube Scanner: [%s].', $this->executable); throw new BuildException($message); } $isOk = false; foreach ($output as $line) { if (preg_match('/SonarQube Scanner [0-9]+\\.[0-9]+/', $line) === 1) { $isOk = true; break; } } if ($isOk) { $message = sprintf('Found SonarQube Scanner: [%s].', $this->executable); $this->log($message, Project::MSG_VERBOSE); } else { $message = sprintf('Could not find name of SonarQube Scanner in version string. Executable appears not to be SonarQube Scanner: [%s].', $this->executable); throw new BuildException($message); } } /** * * @throws BuildException * @return void */ private function validateErrors() { if (($this->errors === '1') || ($this->errors === 'true') || ($this->errors === 'yes')) { $errors = true; } elseif (($this->errors === '0') || ($this->errors === 'false') || ($this->errors === 'no')) { $errors = false; } else { throw new BuildException('Expected a boolean value.'); } if ($errors) { $this->commandLineOptions[] = '--errors'; } } /** * * @throws BuildException * @return void */ private function validateDebug() { if (($this->debug === '1') || ($this->debug === 'true') || ($this->debug === 'yes')) { $debug = true; } elseif (($this->debug === '0') || ($this->debug === 'false') || ($this->debug === 'no')) { $debug = false; } else { throw new BuildException('Expected a boolean value.'); } if ($debug) { $this->commandLineOptions[] = '--debug'; } } /** * * @throws BuildException * @return void */ private function validateConfiguration() { if (($this->configuration === null) || ($this->configuration === '')) { // NOTE: Ignore an empty configuration. This allows for // using Phing properties as attribute values, e.g. // . return; } if (! @file_exists($this->configuration)) { $message = sprintf('Cannot find configuration file [%s].', $this->configuration); throw new BuildException($message); } if (! @is_readable($this->configuration)) { $message = sprintf('Cannot read configuration file [%s].', $this->configuration); throw new BuildException($message); } // TODO: Maybe check file type? } /** * * @throws BuildException * @return void */ private function validateProperties() { $this->properties = $this->parseConfigurationFile(); foreach ($this->propertyElements as $property) { $name = $property->getName(); $value = $property->getValue(); if ($name === null || $name === '') { throw new BuildException('Property name must not be null or empty.'); } if (array_key_exists($name, $this->properties)) { $message = sprintf('Property [%s] overwritten: old value [%s], new value [%s].', $name, $this->properties[$name], $value); $this->log($message, Project::MSG_WARN); } $this->properties[$name] = $value; } // Check if all properties required by SonarQube Scanner are set ... $requiredProperties = array( 'sonar.projectKey', 'sonar.projectName', 'sonar.projectVersion', 'sonar.sources' ); $intersection = array_intersect($requiredProperties, array_keys($this->properties)); if (count($intersection) < count($requiredProperties)) { $message = 'SonarQube Scanner misses some parameters. The following properties are mandatory: ' . implode(', ', $requiredProperties) . '.'; throw new BuildException($message); } } /** * * @return array */ private function parseConfigurationFile() { if (($this->configuration === null) || ($this->configuration === '')) { return array(); } $parser = new SonarConfigurationFileParser($this->configuration, $this->project); return $parser->parse(); } /** * * @return boolean */ private function isWindows() { $operatingSystemName = php_uname('s'); return strtoupper(substr($operatingSystemName, 0, 3)) === 'WIN'; } } . */ require_once 'phing/BuildException.php'; require_once 'phing/Project.php'; require_once 'phing/tasks/ext/sonar/SonarProperty.php'; /** * * @author Bernhard Mendl * @package phing.tasks.ext.sonar */ class SonarConfigurationFileParser { /** * * @var Project */ private $project; /** * * @var string */ private $file; /** * This map holds the properties read from the configuration file. * * @var array */ private $properties; /** * Name of currently parsed property. * * @var string|null */ private $name; /** * Value of currently parsed property. * * @var string */ private $value; /** * * @param string $file * The properties file. */ public function __construct($file, Project $project) { if (($file === null) || ($file === '')) { throw new BuildException('File name must not be null or empty.'); } $this->file = $file; $this->project = $project; } /** * * @throws BuildException * @return array */ public function parse() { $this->properties = array(); $contents = @file_get_contents($this->file); if ($contents === false) { $message = sprintf('Could not read file [%s].', $this->file); throw new BuildException($message); } $lines = explode("\n", $contents); $count = count($lines); $isMultiLine = false; for ($i = 0; $i < $count; $i ++) { $line = $lines[$i]; if ($isMultiLine) { $isMultiLine = $this->extractContinuedValue($line); } else { $this->name = null; $this->value = ''; $isMultiLine = $this->extractNameAndValue($line); } if (($this->name !== null) && (! $isMultiLine)) { if (array_key_exists($this->name, $this->properties)) { $message = sprintf('Property [%s] overwritten: old value [%s], new value [%s].', $this->name, $this->properties[$this->name], $this->value); $this->project->log($message, Project::MSG_WARN); } // Unescape backslashes. $this->value = str_replace('\\\\', '\\', $this->value); $this->properties[$this->name] = $this->value; } } if ($isMultiLine) { $message = sprintf('Last property looks like a multi-lined value, but end of file found. Name = [%s].', $this->name); throw new BuildException($message); } return $this->properties; } /** * * @param string $line * @return boolean */ private function extractNameAndValue($line) { $isMultiLine = false; if ($this->isCommentLine($line)) { return $isMultiLine; } // Find key and value. $hasMatch = preg_match('/\\s*([^=:]*[^=:\\s]+)\\s*[=:]\\s*(.*)$/s', $line, $matches); if (($hasMatch === 1) && (count($matches) === 3)) { $this->name = $matches[1]; $this->value = $matches[2]; $isMultiLine = $this->checkMultiLine(); } return $isMultiLine; } /** * * @param string $line * @return boolean */ private function extractContinuedValue($line) { $isMultiLine = false; if ($this->isCommentLine($line)) { return $isMultiLine; } // Find continued value. $hasMatch = preg_match('/\\s*(.*)$/s', $line, $matches); if (($hasMatch === 1) && (count($matches) === 2)) { $this->value .= $matches[1]; $isMultiLine = $this->checkMultiLine(); } return $isMultiLine; } /** * * @return boolean */ private function checkMultiLine() { $isMultiLine = false; // Is there a single(!) backslash at the end of the line? if (preg_match('/[^\\\]\\\$/', $this->value) === 1) { // Remove last char, i.e. the backslash. $this->value = substr($this->value, 0, -1); $isMultiLine = true; } return $isMultiLine; } /** * * @param string $line * @return boolean */ private function isCommentLine($line) { return preg_match('/^\\s*[!#]/', $line) === 1; } } . */ require_once 'phing/Task.php'; /** * fileHash * * Calculate either MD5 or SHA hash value of a specified file and retun the * value in a property * * @author Johan Persson * @version $Id: d4b97a2e512ffe10394e203d6a94c498e11ca986 $ * @package phing.tasks.ext */ class FileSizeTask extends Task { /** * Property for File * @var PhingFile file */ private $file; /** * Property where the file size will be stored * @var string $property */ private $propertyName = "filesize"; /** * Which file to calculate the file size of * @param PhingFile $file */ public function setFile($file) { $this->file = $file; } /** * Set the name of the property to store the file size * @param $property * @return void */ public function setPropertyName($property) { $this->propertyName = $property; } /** * Main-Method for the Task * * @return void * @throws BuildException */ public function main() { $this->checkFile(); $this->checkPropertyName(); $size = filesize($this->file); if ($size === false) { throw new BuildException(sprintf('[FileSize] Cannot determine size of file: %s', $this->file)); } // publish hash value $this->project->setProperty($this->propertyName, $size); } /** * checks file attribute * @return void * @throws BuildException */ private function checkFile() { // check File if ($this->file === null || strlen($this->file) == 0 ) { throw new BuildException('[FileSize] You must specify an input file.', $this->file); } if (!is_readable($this->file)) { throw new BuildException(sprintf( '[FileSize] Input file does not exist or is not readable: %s', $this->file )); } } /** * checks property attribute * @return void * @throws BuildException */ private function checkPropertyName() { if (is_null($this->propertyName) || strlen($this->propertyName) === 0 ) { throw new BuildException('[FileSize] Property name for publishing file size is not set'); } } } . */ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/io/Writer.php'; require_once 'phing/system/util/Properties.php'; require_once 'phing/tasks/ext/phpunit/PHPUnitUtil.php'; require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php'; /** * Transforms information in a code coverage database to XML * * @author Michiel Rook * @version $Id: 9a15437e8ba7eb26f59aa20fd6c10e682b26e697 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageReportTask extends Task { private $outfile = "coverage.xml"; private $transformers = array(); /** the classpath to use (optional) */ private $classpath = null; /** the path to the GeSHi library (optional) */ private $geshipath = ""; /** the path to the GeSHi language files (optional) */ private $geshilanguagespath = ""; /** * @param Path $classpath */ public function setClasspath(Path $classpath) { if ($this->classpath === null) { $this->classpath = $classpath; } else { $this->classpath->append($classpath); } } /** * @return null|Path */ public function createClasspath() { $this->classpath = new Path(); return $this->classpath; } /** * @param $path */ public function setGeshiPath($path) { $this->geshipath = $path; } /** * @param $path */ public function setGeshiLanguagesPath($path) { $this->geshilanguagespath = $path; } /** * */ public function __construct() { $this->doc = new DOMDocument(); $this->doc->encoding = 'UTF-8'; $this->doc->formatOutput = true; $this->doc->appendChild($this->doc->createElement('snapshot')); } /** * @param $outfile */ public function setOutfile($outfile) { $this->outfile = $outfile; } /** * Generate a report based on the XML created by this task */ public function createReport() { $transformer = new CoverageReportTransformer($this); $this->transformers[] = $transformer; return $transformer; } /** * @param $packageName * @return null */ protected function getPackageElement($packageName) { $packages = $this->doc->documentElement->getElementsByTagName('package'); foreach ($packages as $package) { if ($package->getAttribute('name') == $packageName) { return $package; } } return null; } /** * @param $packageName * @param $element */ protected function addClassToPackage($packageName, $element) { $package = $this->getPackageElement($packageName); if ($package === null) { $package = $this->doc->createElement('package'); $package->setAttribute('name', $packageName); $this->doc->documentElement->appendChild($package); } $package->appendChild($element); } /** * Adds a subpackage to their package * * @param string $packageName The name of the package * @param string $subpackageName The name of the subpackage * * @author Benjamin Schultz * @return void */ protected function addSubpackageToPackage($packageName, $subpackageName) { $package = $this->getPackageElement($packageName); $subpackage = $this->getSubpackageElement($subpackageName); if ($package === null) { $package = $this->doc->createElement('package'); $package->setAttribute('name', $packageName); $this->doc->documentElement->appendChild($package); } if ($subpackage === null) { $subpackage = $this->doc->createElement('subpackage'); $subpackage->setAttribute('name', $subpackageName); } $package->appendChild($subpackage); } /** * Returns the subpackage element * * @param string $subpackageName The name of the subpackage * * @author Benjamin Schultz * @return DOMNode|null null when no DOMNode with the given name exists */ protected function getSubpackageElement($subpackageName) { $subpackages = $this->doc->documentElement->getElementsByTagName('subpackage'); foreach ($subpackages as $subpackage) { if ($subpackage->getAttribute('name') == $subpackageName) { return $subpackage; } } return null; } /** * Adds a class to their subpackage * * @param string $classname The name of the class * @param DOMNode $element The dom node to append to the subpackage element * * @author Benjamin Schultz * @return void */ protected function addClassToSubpackage($classname, $element) { $subpackageName = PHPUnitUtil::getSubpackageName($classname); $subpackage = $this->getSubpackageElement($subpackageName); if ($subpackage === null) { $subpackage = $this->doc->createElement('subpackage'); $subpackage->setAttribute('name', $subpackageName); $this->doc->documentElement->appendChild($subpackage); } $subpackage->appendChild($element); } /** * @param $source * @return string */ protected function stripDiv($source) { $openpos = strpos($source, "", $openpos); $line = substr($source, $closepos + 1); $tagclosepos = strpos($line, ""); $line = substr($line, 0, $tagclosepos); return $line; } /** * @param $filename * @return array */ protected function highlightSourceFile($filename) { if ($this->geshipath) { require_once $this->geshipath . '/geshi.php'; $source = file_get_contents($filename); $geshi = new GeSHi($source, 'php', $this->geshilanguagespath); $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); $geshi->enable_strict_mode(true); $geshi->enable_classes(true); $geshi->set_url_for_keyword_group(3, ''); $html = $geshi->parse_code(); $lines = preg_split("##", $html); // skip first and last line array_pop($lines); array_shift($lines); $lines = array_filter($lines); $lines = array_map(array($this, 'stripDiv'), $lines); return $lines; } else { $lines = file($filename); for ($i = 0; $i < count($lines); $i++) { $line = $lines[$i]; $line = rtrim($line); if (function_exists('mb_check_encoding') && mb_check_encoding($line, 'UTF-8')) { $lines[$i] = $line; } else { if (function_exists('mb_convert_encoding')) { $lines[$i] = mb_convert_encoding($line, 'UTF-8'); } else { $lines[$i] = utf8_encode($line); } } } return $lines; } } /** * @param $filename * @param $coverageInformation * @param int $classStartLine * @return DOMElement */ protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1) { $sourceElement = $this->doc->createElement('sourcefile'); $sourceElement->setAttribute('name', basename($filename)); /** * Add original/full filename to document */ $sourceElement->setAttribute('sourcefile', $filename); $filelines = $this->highlightSourceFile($filename); $linenr = 1; foreach ($filelines as $line) { $lineElement = $this->doc->createElement('sourceline'); $lineElement->setAttribute( 'coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0') ); if ($linenr == $classStartLine) { $lineElement->setAttribute('startclass', 1); } $textnode = $this->doc->createTextNode($line); $lineElement->appendChild($textnode); $sourceElement->appendChild($lineElement); $linenr++; } return $sourceElement; } /** * Transforms the coverage information * * @param string $filename The filename * @param array $coverageInformation Array with covergae information * * @author Michiel Rook * @author Benjamin Schultz * @return void */ protected function transformCoverageInformation($filename, $coverageInformation) { $classes = PHPUnitUtil::getDefinedClasses($filename, $this->classpath); if (is_array($classes)) { foreach ($classes as $classname) { $reflection = new ReflectionClass($classname); $methods = $reflection->getMethods(); if (method_exists($reflection, 'getShortName')) { $className = $reflection->getShortName(); } else { $className = $reflection->getName(); } $classElement = $this->doc->createElement('class'); $classElement->setAttribute('name', $className); $packageName = PHPUnitUtil::getPackageName($reflection->getName()); $subpackageName = PHPUnitUtil::getSubpackageName($reflection->getName()); if ($subpackageName !== null) { $this->addSubpackageToPackage($packageName, $subpackageName); $this->addClassToSubpackage($reflection->getName(), $classElement); } else { $this->addClassToPackage($packageName, $classElement); } $classStartLine = $reflection->getStartLine(); $methodscovered = 0; $methodcount = 0; // Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off if ($reflection->getParentClass() == null && count($reflection->getInterfaces()) == 0) { unset($coverageInformation[$classStartLine + 1]); } else { unset($coverageInformation[$classStartLine]); } // Remove out-of-bounds info unset($coverageInformation[0]); reset($coverageInformation); foreach ($methods as $method) { // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't if ($method->getDeclaringClass()->getName() != $reflection->getName()) { continue; } // small fix for XDEBUG_CC_UNUSED if (isset($coverageInformation[$method->getStartLine()])) { unset($coverageInformation[$method->getStartLine()]); } if (isset($coverageInformation[$method->getEndLine()])) { unset($coverageInformation[$method->getEndLine()]); } if ($method->isAbstract()) { continue; } $linenr = key($coverageInformation); while ($linenr !== null && $linenr < $method->getStartLine()) { next($coverageInformation); $linenr = key($coverageInformation); } $methodCoveredCount = 0; $methodTotalCount = 0; $methodHasCoveredLine = false; while ($linenr !== null && $linenr <= $method->getEndLine()) { $methodTotalCount++; $methodHasCoveredLine = true; // set covered when CODE is other than -1 (not executed) if ($coverageInformation[$linenr] > 0 || $coverageInformation[$linenr] == -2) { $methodCoveredCount++; } next($coverageInformation); $linenr = key($coverageInformation); } if (($methodTotalCount == $methodCoveredCount) && $methodHasCoveredLine) { $methodscovered++; } $methodcount++; } $statementcount = count( array_filter( $coverageInformation, create_function('$var', 'return ($var != -2);') ) ); $statementscovered = count( array_filter( $coverageInformation, create_function('$var', 'return ($var >= 0);') ) ); $classElement->appendChild( $this->transformSourceFile($filename, $coverageInformation, $classStartLine) ); $classElement->setAttribute('methodcount', $methodcount); $classElement->setAttribute('methodscovered', $methodscovered); $classElement->setAttribute('statementcount', $statementcount); $classElement->setAttribute('statementscovered', $statementscovered); $classElement->setAttribute('totalcount', $methodcount + $statementcount); $classElement->setAttribute('totalcovered', $methodscovered + $statementscovered); } } } protected function calculateStatistics() { $packages = $this->doc->documentElement->getElementsByTagName('package'); $totalmethodcount = 0; $totalmethodscovered = 0; $totalstatementcount = 0; $totalstatementscovered = 0; foreach ($packages as $package) { $methodcount = 0; $methodscovered = 0; $statementcount = 0; $statementscovered = 0; $subpackages = $package->getElementsByTagName('subpackage'); foreach ($subpackages as $subpackage) { $subpackageMethodCount = 0; $subpackageMethodsCovered = 0; $subpackageStatementCount = 0; $subpackageStatementsCovered = 0; $subpackageClasses = $subpackage->getElementsByTagName('class'); foreach ($subpackageClasses as $subpackageClass) { $subpackageMethodCount += $subpackageClass->getAttribute('methodcount'); $subpackageMethodsCovered += $subpackageClass->getAttribute('methodscovered'); $subpackageStatementCount += $subpackageClass->getAttribute('statementcount'); $subpackageStatementsCovered += $subpackageClass->getAttribute('statementscovered'); } $subpackage->setAttribute('methodcount', $subpackageMethodCount); $subpackage->setAttribute('methodscovered', $subpackageMethodsCovered); $subpackage->setAttribute('statementcount', $subpackageStatementCount); $subpackage->setAttribute('statementscovered', $subpackageStatementsCovered); $subpackage->setAttribute('totalcount', $subpackageMethodCount + $subpackageStatementCount); $subpackage->setAttribute('totalcovered', $subpackageMethodsCovered + $subpackageStatementsCovered); } $classes = $package->getElementsByTagName('class'); foreach ($classes as $class) { $methodcount += $class->getAttribute('methodcount'); $methodscovered += $class->getAttribute('methodscovered'); $statementcount += $class->getAttribute('statementcount'); $statementscovered += $class->getAttribute('statementscovered'); } $package->setAttribute('methodcount', $methodcount); $package->setAttribute('methodscovered', $methodscovered); $package->setAttribute('statementcount', $statementcount); $package->setAttribute('statementscovered', $statementscovered); $package->setAttribute('totalcount', $methodcount + $statementcount); $package->setAttribute('totalcovered', $methodscovered + $statementscovered); $totalmethodcount += $methodcount; $totalmethodscovered += $methodscovered; $totalstatementcount += $statementcount; $totalstatementscovered += $statementscovered; } $this->doc->documentElement->setAttribute('methodcount', $totalmethodcount); $this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered); $this->doc->documentElement->setAttribute('statementcount', $totalstatementcount); $this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered); $this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount); $this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered); } public function main() { $coverageDatabase = $this->project->getProperty('coverage.database'); if (!$coverageDatabase) { throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); } $database = new PhingFile($coverageDatabase); $this->log("Transforming coverage report"); $props = new Properties(); $props->load($database); foreach ($props->keys() as $filename) { $file = unserialize($props->getProperty($filename)); $this->transformCoverageInformation($file['fullname'], $file['coverage']); } $this->calculateStatistics(); $this->doc->save($this->outfile); foreach ($this->transformers as $transformer) { $transformer->setXmlDocument($this->doc); $transformer->transform(); } } } . */ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/io/Writer.php'; require_once 'phing/system/util/Properties.php'; require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; /** * Initializes a code coverage database * * @author Michiel Rook * @version $Id: bde7020012ba4f24e0d97768c76a5a8af99a6fbb $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageSetupTask extends Task { /** the list of filesets containing the .php filename rules */ private $filesets = array(); /** Any filelists of files containing the .php filenames */ private $filelists = array(); /** the filename of the coverage database */ private $database = "coverage.db"; /** the classpath to use (optional) */ private $classpath = null; /** * Add a new fileset containing the .php files to process * * @param FileSet the new fileset containing .php files */ public function addFileSet(FileSet $fileset) { $this->filesets[] = $fileset; } /** * Supports embedded element. * @return FileList */ public function createFileList() { $num = array_push($this->filelists, new FileList()); return $this->filelists[$num - 1]; } /** * Sets the filename of the coverage database to use * * @param string the filename of the database */ public function setDatabase($database) { $this->database = $database; } /** * @param Path $classpath */ public function setClasspath(Path $classpath) { if ($this->classpath === null) { $this->classpath = $classpath; } else { $this->classpath->append($classpath); } } /** * @return null|Path */ public function createClasspath() { $this->classpath = new Path(); return $this->classpath; } /** * Iterate over all filesets and return the filename of all files. * * @return array an array of (basedir, filenames) pairs */ private function getFilenames() { $files = array(); foreach ($this->filelists as $fl) { try { $list = $fl->getFiles($this->project); foreach ($list as $file) { $fs = new PhingFile(strval($fl->getDir($this->project)), $file); $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); } } catch (BuildException $be) { $this->log($be->getMessage(), Project::MSG_WARN); } } foreach ($this->filesets as $fileset) { $ds = $fileset->getDirectoryScanner($this->project); $ds->scan(); $includedFiles = $ds->getIncludedFiles(); foreach ($includedFiles as $file) { $fs = new PhingFile(realpath($ds->getBaseDir()), $file); $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath()); } } return $files; } public function init() { } public function main() { $files = $this->getFilenames(); $this->log("Setting up coverage database for " . count($files) . " files"); $props = new Properties(); foreach ($files as $file) { $fullname = $file['fullname']; $filename = $file['key']; $props->setProperty($filename, serialize(array('fullname' => $fullname, 'coverage' => array()))); } $dbfile = new PhingFile($this->database); $props->store($dbfile); $this->project->setProperty('coverage.database', $dbfile->getAbsolutePath()); } } . */ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/util/Properties.php'; require_once 'phing/types/Excludes.php'; /** * Stops the build if any of the specified coverage threshold was not reached * * @author Benjamin Schultz * @version $Id: 1cf68f1a4ec652811a5fd9db8353cae9a88ee03e $ * @package phing.tasks.ext.coverage * @since 2.4.1 */ class CoverageThresholdTask extends Task { /** * Holds an optional classpath * * @var Path */ private $_classpath = null; /** * Holds the exclusions * * @var Excludes */ private $_excludes = null; /** * Holds an optional database file * * @var PhingFile */ private $_database = null; /** * Holds the coverage threshold for the entire project * * @var integer */ private $_perProject = 25; /** * Holds the coverage threshold for any class * * @var integer */ private $_perClass = 25; /** * Holds the coverage threshold for any method * * @var integer */ private $_perMethod = 25; /** * Holds the minimum found coverage value for a class * * @var integer */ private $_minClassCoverageFound = null; /** * Holds the minimum found coverage value for a method * * @var integer */ private $_minMethodCoverageFound = null; /** * Number of statements in the entire project * * @var integer */ private $_projectStatementCount = 0; /** * Number of covered statements in the entire project * * @var integer */ private $_projectStatementsCovered = 0; /** * Whether to enable detailed logging * * @var boolean */ private $_verbose = false; /** * Sets an optional classpath * * @param Path $classpath The classpath */ public function setClasspath(Path $classpath) { if ($this->_classpath === null) { $this->_classpath = $classpath; } else { $this->_classpath->append($classpath); } } /** * Sets the optional coverage database to use * * @param PhingFile The database file */ public function setDatabase(PhingFile $database) { $this->_database = $database; } /** * Create classpath object * * @return Path */ public function createClasspath() { $this->_classpath = new Path(); return $this->_classpath; } /** * Sets the coverage threshold for entire project * * @param integer $threshold Coverage threshold for entire project */ public function setPerProject($threshold) { $this->_perProject = $threshold; } /** * Sets the coverage threshold for any class * * @param integer $threshold Coverage threshold for any class */ public function setPerClass($threshold) { $this->_perClass = $threshold; } /** * Sets the coverage threshold for any method * * @param integer $threshold Coverage threshold for any method */ public function setPerMethod($threshold) { $this->_perMethod = $threshold; } /** * Sets whether to enable detailed logging or not * * @param boolean $verbose */ public function setVerbose($verbose) { $this->_verbose = StringHelper::booleanValue($verbose); } /** * Filter covered statements * * @param integer $var Coverage CODE/count * @return boolean */ protected function filterCovered($var) { return ($var >= 0 || $var === -2); } /** * Create excludes object * * @return Excludes */ public function createExcludes() { $this->_excludes = new Excludes($this->project); return $this->_excludes; } /** * Calculates the coverage threshold * * @param string $filename The filename to analyse * @param array $coverageInformation Array with coverage information * @throws BuildException */ protected function calculateCoverageThreshold($filename, $coverageInformation) { $classes = PHPUnitUtil::getDefinedClasses($filename, $this->_classpath); if (is_array($classes)) { foreach ($classes as $className) { // Skip class if excluded from coverage threshold validation if ($this->_excludes !== null) { if (in_array($className, $this->_excludes->getExcludedClasses())) { continue; } } $reflection = new ReflectionClass($className); $classStartLine = $reflection->getStartLine(); // Strange PHP5 reflection bug, classes without parent class // or implemented interfaces seem to start one line off if ($reflection->getParentClass() === null && count($reflection->getInterfaces()) === 0 ) { unset($coverageInformation[$classStartLine + 1]); } else { unset($coverageInformation[$classStartLine]); } reset($coverageInformation); $methods = $reflection->getMethods(); foreach ($methods as $method) { // PHP5 reflection considers methods of a parent class // to be part of a subclass, we don't if ($method->getDeclaringClass()->getName() != $reflection->getName()) { continue; } // Skip method if excluded from coverage threshold validation if ($this->_excludes !== null) { $excludedMethods = $this->_excludes->getExcludedMethods(); if (isset($excludedMethods[$className])) { if (in_array($method->getName(), $excludedMethods[$className]) || in_array($method->getName() . '()', $excludedMethods[$className]) ) { continue; } } } $methodStartLine = $method->getStartLine(); $methodEndLine = $method->getEndLine(); // small fix for XDEBUG_CC_UNUSED if (isset($coverageInformation[$methodStartLine])) { unset($coverageInformation[$methodStartLine]); } if (isset($coverageInformation[$methodEndLine])) { unset($coverageInformation[$methodEndLine]); } if ($method->isAbstract()) { continue; } $lineNr = key($coverageInformation); while ($lineNr !== null && $lineNr < $methodStartLine) { next($coverageInformation); $lineNr = key($coverageInformation); } $methodStatementsCovered = 0; $methodStatementCount = 0; while ($lineNr !== null && $lineNr <= $methodEndLine) { $methodStatementCount++; $lineCoverageInfo = $coverageInformation[$lineNr]; // set covered when CODE is other than -1 (not executed) if ($lineCoverageInfo > 0 || $lineCoverageInfo === -2) { $methodStatementsCovered++; } next($coverageInformation); $lineNr = key($coverageInformation); } if ($methodStatementCount > 0) { $methodCoverage = ($methodStatementsCovered / $methodStatementCount) * 100; } else { $methodCoverage = 0; } if ($methodCoverage < $this->_perMethod && !$method->isAbstract() ) { throw new BuildException( 'The coverage (' . round($methodCoverage, 2) . '%) ' . 'for method "' . $method->getName() . '" is lower' . ' than the specified threshold (' . $this->_perMethod . '%), see file: "' . $filename . '"' ); } elseif ($methodCoverage < $this->_perMethod && $method->isAbstract() && $this->_verbose === true ) { $this->log( 'Skipped coverage threshold for abstract method "' . $method->getName() . '"' ); } // store the minimum coverage value for logging (see #466) if ($this->_minMethodCoverageFound !== null) { if ($this->_minMethodCoverageFound > $methodCoverage) { $this->_minMethodCoverageFound = $methodCoverage; } } else { $this->_minMethodCoverageFound = $methodCoverage; } } $classStatementCount = count($coverageInformation); $classStatementsCovered = count( array_filter( $coverageInformation, array($this, 'filterCovered') ) ); if ($classStatementCount > 0) { $classCoverage = ($classStatementsCovered / $classStatementCount) * 100; } else { $classCoverage = 0; } if ($classCoverage < $this->_perClass && !$reflection->isAbstract() ) { throw new BuildException( 'The coverage (' . round($classCoverage, 2) . '%) for class "' . $reflection->getName() . '" is lower than the ' . 'specified threshold (' . $this->_perClass . '%), ' . 'see file: "' . $filename . '"' ); } elseif ($classCoverage < $this->_perClass && $reflection->isAbstract() && $this->_verbose === true ) { $this->log( 'Skipped coverage threshold for abstract class "' . $reflection->getName() . '"' ); } // store the minimum coverage value for logging (see #466) if ($this->_minClassCoverageFound !== null) { if ($this->_minClassCoverageFound > $classCoverage) { $this->_minClassCoverageFound = $classCoverage; } } else { $this->_minClassCoverageFound = $classCoverage; } $this->_projectStatementCount += $classStatementCount; $this->_projectStatementsCovered += $classStatementsCovered; } } } public function main() { if ($this->_database === null) { $coverageDatabase = $this->project ->getProperty('coverage.database'); if (!$coverageDatabase) { throw new BuildException( 'Either include coverage-setup in your build file or set ' . 'the "database" attribute' ); } $database = new PhingFile($coverageDatabase); } else { $database = $this->_database; } $this->log( 'Calculating coverage threshold: min. ' . $this->_perProject . '% per project, ' . $this->_perClass . '% per class and ' . $this->_perMethod . '% per method is required' ); $props = new Properties(); $props->load($database); foreach ($props->keys() as $filename) { $file = unserialize($props->getProperty($filename)); // Skip file if excluded from coverage threshold validation if ($this->_excludes !== null) { if (in_array($file['fullname'], $this->_excludes->getExcludedFiles())) { continue; } } $this->calculateCoverageThreshold( $file['fullname'], $file['coverage'] ); } if ($this->_projectStatementCount > 0) { $coverage = ($this->_projectStatementsCovered / $this->_projectStatementCount) * 100; } else { $coverage = 0; } if ($coverage < $this->_perProject) { throw new BuildException( 'The coverage (' . round($coverage, 2) . '%) for the entire project ' . 'is lower than the specified threshold (' . $this->_perProject . '%)' ); } $this->log( 'Passed coverage threshold. Minimum found coverage values are: ' . round($coverage, 2) . '% per project, ' . round($this->_minClassCoverageFound, 2) . '% per class and ' . round($this->_minMethodCoverageFound, 2) . '% per method' ); } } . */ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/io/Writer.php'; require_once 'phing/system/util/Properties.php'; require_once 'phing/tasks/ext/coverage/CoverageMerger.php'; /** * Merges code coverage snippets into a code coverage database * * @author Michiel Rook * @version $Id: 6d4732d2b352c992dc03cd92cd83ad1b81bf9e45 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageMergerTask extends Task { /** the list of filesets containing the .php filename rules */ private $filesets = array(); /** * Add a new fileset containing the .php files to process * * @param FileSet the new fileset containing .php files */ public function addFileSet(FileSet $fileset) { $this->filesets[] = $fileset; } /** * Iterate over all filesets and return all the filenames. * * @return array an array of filenames */ private function getFilenames() { $files = array(); foreach ($this->filesets as $fileset) { $ds = $fileset->getDirectoryScanner($this->project); $ds->scan(); $includedFiles = $ds->getIncludedFiles(); foreach ($includedFiles as $file) { $fs = new PhingFile(basename($ds->getBaseDir()), $file); $files[] = $fs->getAbsolutePath(); } } return $files; } public function main() { $files = $this->getFilenames(); $this->log("Merging " . count($files) . " coverage files"); foreach ($files as $file) { $coverageInformation = unserialize(file_get_contents($file)); CoverageMerger::merge($this->project, array($coverageInformation)); } } } . */ require_once 'phing/system/util/Properties.php'; /** * Saves coverage output of the test to a specified database * * @author Michiel Rook * @version $Id: 18a66018595b27816f2bd0ac5f2d67a42ea16416 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageMerger { /** * @param $left * @param $right * @return array */ private static function mergeCodeCoverage($left, $right) { $coverageMerged = array(); reset($left); reset($right); while (current($left) !== false && current($right) !== false) { $linenr_left = key($left); $linenr_right = key($right); if ($linenr_left < $linenr_right) { $coverageMerged[$linenr_left] = current($left); next($left); } elseif ($linenr_right < $linenr_left) { $coverageMerged[$linenr_right] = current($right); next($right); } else { if ((current($left) < 0) || (current($right) < 0)) { $coverageMerged[$linenr_right] = current($right); } else { $coverageMerged[$linenr_right] = current($left) + current($right); } next($left); next($right); } } while (current($left) !== false) { $coverageMerged[key($left)] = current($left); next($left); } while (current($right) !== false) { $coverageMerged[key($right)] = current($right); next($right); } return $coverageMerged; } /** * @param Project $project * @return Properties * @throws BuildException */ protected static function _getDatabase($project) { $coverageDatabase = $project->getProperty('coverage.database'); if (!$coverageDatabase) { throw new BuildException("Property coverage.database is not set - please include coverage-setup in your build file"); } $database = new PhingFile($coverageDatabase); $props = new Properties(); $props->load($database); return $props; } /** * @param $project * @return array * @throws BuildException */ public static function getWhiteList($project) { $whitelist = array(); $props = self::_getDatabase($project); foreach ($props->getProperties() as $property) { $data = unserialize($property); $whitelist[] = $data['fullname']; } return $whitelist; } /** * @param $project * @param $codeCoverageInformation * @throws BuildException * @throws IOException */ public static function merge($project, $codeCoverageInformation) { $props = self::_getDatabase($project); $coverageTotal = $codeCoverageInformation; foreach ($coverageTotal as $filename => $data) { $lines = array(); $filename = strtolower($filename); if ($props->getProperty($filename) != null) { foreach ($data as $_line => $_data) { if ($_data === null) { continue; } if (is_array($_data)) { $count = count($_data); if ($count == 0) { $count = -1; } } else { if ($_data == -1) { // not executed $count = -1; } else { if ($_data == -2) { // dead code $count = -2; } } } $lines[$_line] = $count; } ksort($lines); $file = unserialize($props->getProperty($filename)); $left = $file['coverage']; $coverageMerged = CoverageMerger::mergeCodeCoverage($left, $lines); $file['coverage'] = $coverageMerged; $props->setProperty($filename, serialize($file)); } } $props->store(); } } . */ require_once 'phing/Task.php'; require_once 'phing/system/io/PhingFile.php'; require_once 'phing/system/io/FileWriter.php'; require_once 'phing/util/ExtendedFileStream.php'; /** * Transform a Phing/Xdebug code coverage xml report. * The default transformation generates an html report in framed style. * * @author Michiel Rook * @version $Id: d3a5fbec986f8d4d1fde4875192fb243c82f1e68 $ * @package phing.tasks.ext.coverage * @since 2.1.0 */ class CoverageReportTransformer { private $task = null; private $styleDir = ""; /** * @var PhingFile */ private $toDir = ""; private $document = null; /** title of the project, used in the coverage report */ private $title = ""; /** * Whether to use the sorttable JavaScript library, defaults to false * See {@link http://www.kryogenix.org/code/browser/sorttable/)} * * @var boolean */ private $useSortTable = false; /** * @param Task $task */ public function __construct(Task $task) { $this->task = $task; } /** * @param $styleDir */ public function setStyleDir($styleDir) { $this->styleDir = $styleDir; } /** * @param PhingFile $toDir */ public function setToDir(PhingFile $toDir) { $this->toDir = $toDir; } /** * @param $document */ public function setXmlDocument($document) { $this->document = $document; } /** * Setter for title parameter * @param $title */ public function setTitle($title) { $this->title = $title; } /** * Sets whether to use the sorttable JavaScript library, defaults to false * See {@link http://www.kryogenix.org/code/browser/sorttable/)} * * @param boolean $useSortTable */ public function setUseSortTable($useSortTable) { $this->useSortTable = (boolean) $useSortTable; } public function transform() { if (!$this->toDir->exists()) { throw new BuildException("Directory '" . $this->toDir . "' does not exist"); } $xslfile = $this->getStyleSheet(); $xsl = new DOMDocument(); $xsl->load($xslfile->getAbsolutePath()); $proc = new XSLTProcessor(); if (defined('XSL_SECPREF_WRITE_FILE')) { if (version_compare(PHP_VERSION, '5.4', "<")) { ini_set("xsl.security_prefs", XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); } else { $proc->setSecurityPrefs(XSL_SECPREF_WRITE_FILE | XSL_SECPREF_CREATE_DIRECTORY); } } $proc->importStyleSheet($xsl); ExtendedFileStream::registerStream(); $toDir = (string) $this->toDir; // urlencode() the path if we're on Windows if (FileSystem::getFileSystem()->getSeparator() == '\\') { $toDir = urlencode($toDir); } // no output for the framed report // it's all done by extension... $proc->setParameter('', 'output.dir', $toDir); $proc->setParameter('', 'output.sorttable', $this->useSortTable); $proc->setParameter('', 'document.title', $this->title); $proc->transformToXML($this->document); ExtendedFileStream::unregisterStream(); } /** * @return PhingFile * @throws BuildException */ private function getStyleSheet() { $xslname = "coverage-frames.xsl"; if ($this->styleDir) { $file = new PhingFile($this->styleDir, $xslname); } else { $path = Phing::getResourcePath("phing/etc/$xslname"); if ($path === null) { $path = Phing::getResourcePath("etc/$xslname"); if ($path === null) { throw new BuildException("Could not find $xslname in resource path"); } } $file = new PhingFile($path); } if (!$file->exists()) { throw new BuildException("Could not find file " . $file->getPath()); } return $file; } } . */ require_once 'phing/tasks/system/MatchingTask.php'; include_once 'phing/util/SourceFileScanner.php'; include_once 'phing/mappers/MergeMapper.php'; include_once 'phing/util/StringHelper.php'; /** * Encodes files using Zeng Guard Encoder * * @author Petr Rybak * @version $Id: aacbd9ea1b3f9e13178cea0f5ff625f921076a32 $ * @package phing.tasks.ext.zendguard * @since 2.4.3 */ class ZendGuardEncodeTask extends MatchingTask { protected $filesets = array(); protected $encodeCommand; /** * TASK PROPERTIES * * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf * for more information on how to use ZendGuard * */ /** * Permanently deletes (see warning below) the original source files specified in the * SourceInputPath and saves the encoded files in its place. * This option has no option parameter. * When this option is use, do not use the output_file parameter. * * Warning: * To avoid permanent loss of non-encoded scripts, make a backup. Deleted files * cannot be restored or recovered and will be permanently deleted with this option. * If you are unsure about deleting the source files, use the ––rename-source option * instead * * @var bool */ protected $deleteSource = true; /** * Move the original source file to . and save the encoded file in its * place. * * If specified deleteSource will be automatically disabled. * * @var string */ protected $renameSourceExt = null; /** * Turns short PHP tag (“zendEncoderPath = $value; } /** * @param $value */ public function setPrivateKeyPath($value) { $this->privateKeyPath = $value; } /** * @param $value */ public function setShortTags($value) { $this->shortTags = (bool) $value; } /** * @param $value */ public function setAspTags($value) { $this->aspTags = (bool) $value; } /** * @param $value */ public function setDeleteSource($value) { $this->shortTags = (bool) $value; } /** * @param $value */ public function setUseCrypto($value) { $this->useCrypto = (bool) $value; } /** * @param $value */ public function setObfuscationLevel($value) { $this->obfuscationLevel = (int) $value; } /** * @param $value */ public function setLicenseProduct($value) { $this->licenseProduct = (bool) $value; } /** * @param $value */ public function setPrologFile($value) { $this->prologFile = $value; } /** * @param $value */ public function setSignProduct($value) { $this->signProduct = (bool) $value; } /** * @param $value */ public function setForceEncode($value) { $this->forceEncode = (bool) $value; } /** * @param $value */ public function setEncodedOnly($value) { $this->encodedOnly = (bool) $value; } /** * @param $value */ public function setIgnoreFileModes($value) { $this->ignoreFileModes = (bool) $value; } /** * @param $value */ public function setExpires($value) { $this->expires = $value; } /** * @param $value */ public function setProductName($value) { $this->productName = $value; } /** * @param $value */ public function setOptMask($value) { $this->optMask = (int) $value; } /** * @param $value */ public function setRenameSourceExt($value) { $this->renameSourceExt = $value; } /** * @param $value */ public function setNoHeader($value) { $this->noHeader = (bool) $value; } /** * Add a new fileset. * * @return FileSet */ public function createFileSet() { $this->fileset = new ZendGuardFileSet(); $this->filesets[] = $this->fileset; return $this->fileset; } /** * Verifies that the configuration is correct * * @throws BuildException */ protected function verifyConfiguration() { // Check that the zend encoder path is specified if (empty($this->zendEncoderPath)) { throw new BuildException("Zend Encoder path must be specified"); } // verify that the zend encoder binary exists if (!file_exists($this->zendEncoderPath)) { throw new BuildException("Zend Encoder not found on path " . $this->zendEncoderPath); } // if either sign or license is required the private key path needs to be defined // and the file has to exist and product name has to be specified if ($this->signProduct || $this->licenseProduct) { if (empty($this->privateKeyPath)) { throw new BuildException("Licensing or signing requested but privateKeyPath not provided."); } if (!is_readable($this->privateKeyPath)) { throw new BuildException("Licensing or signing requested but private key path doesn't exist or is unreadable."); } if (empty($this->productName)) { throw new BuildException("Licensing or signing requested but product name not provided."); } } // verify prolog file exists if (!empty($this->prologFile)) { if (!file_exists($this->prologFile)) { throw new BuildException("The prolog file doesn't exist: " . $this->prologFile); } } } /** * Do the work * * @throws BuildException */ public function main() { $this->verifyConfiguration(); $this->prepareEncoderCommand(); try { if (empty($this->filesets)) { throw new BuildException("You must supply nested fileset.", $this->getLocation()); } $encodedFilesCounter = 0; foreach ($this->filesets as $fs) { /* @var $fs FileSet */ /* @var $fsBasedir PhingFile */ $fsBasedir = $fs->getDir($this->project)->getAbsolutePath(); $files = $fs->getFiles($this->project, false); foreach ($files as $file) { $f = new PhingFile($fsBasedir, $file); if ($f->isFile()) { $path = $f->getAbsolutePath(); $this->log("Encoding " . $path, Project::MSG_VERBOSE); $this->encodeFile($path); $encodedFilesCounter++; } } } $this->log("Encoded files: " . $encodedFilesCounter); } catch (IOException $ioe) { $msg = "Problem encoding files: " . $ioe->getMessage(); throw new BuildException($msg, $ioe, $this->getLocation()); } } /** * Prepares the main part of the command that will be * used to encode the given file(s). */ protected function prepareEncoderCommand() { $command = $this->zendEncoderPath . " "; if (!empty($this->renameSourceExt)) { $command .= " --rename-source " . $this->renameSourceExt . " "; } elseif ($this->deleteSource) { // delete source $command .= " --delete-source "; } // short tags $command .= " --short-tags " . (($this->shortTags) ? 'on' : 'off') . " "; // asp tags $command .= " --asp-tags " . (($this->aspTags) ? 'on' : 'off') . " "; // use crypto if ($this->useCrypto) { $command .= " --use-crypto "; } // ignore file modes if ($this->ignoreFileModes) { $command .= " --ignore-file-modes "; } // force encode if ($this->forceEncode) { $command .= " --force-encode "; } // expires if (!empty($this->expires)) { $command .= " --expires " . $this->expires . " "; } // insert prolog file name or no-header if (!empty($this->prologFile)) { $command .= " --prolog-filename " . $this->prologFile . " "; } elseif ($this->noHeader) { // no-header $command .= " --no-header "; } // obfuscation level if ($this->obfuscationLevel > 0) { $command .= " --obfuscation-level " . $this->obfuscationLevel . " "; } // encoded only if ($this->encodedOnly) { $command .= " --encoded-only "; } // opt mask if (null !== $this->optMask) { $command .= " --optimizations " . $this->optMask . " "; } // Signing or licensing if ($this->signProduct) { $command .= " --sign-product " . $this->productName . " --private-key " . $this->privateKeyPath . " "; } elseif ($this->licenseProduct) { $command .= " --license-product " . $this->productName . " --private-key " . $this->privateKeyPath . " "; } // add a blank space $command .= " "; $this->encodeCommand = $command; } /** * Encodes a file using currently defined Zend Guard settings * * @param string $filePath Path to the encoded file * @throws BuildException * @return bool */ protected function encodeFile($filePath) { $command = $this->encodeCommand . $filePath . ' 2>&1'; $this->log('Running: ' . $command, Project::MSG_VERBOSE); $tmp = exec($command, $output, $return_var); if ($return_var !== 0) { throw new BuildException("Encoding failed. \n Msg: " . $tmp . " \n Encode command: " . $command); } return true; } } /** * This is a FileSet with the to specify permissions. * * Permissions are currently not implemented by PEAR Archive_Tar, * but hopefully they will be in the future. * * @package phing.tasks.ext.zendguard */ class ZendGuardFileSet extends FileSet { private $files = null; /** * Get a list of files and directories specified in the fileset. * @param Project $p * @param bool $includeEmpty * @throws BuildException * @return array a list of file and directory names, relative to * the baseDir for the project. */ public function getFiles(Project $p, $includeEmpty = true) { if ($this->files === null) { $ds = $this->getDirectoryScanner($p); $this->files = $ds->getIncludedFiles(); } // if ($this->files===null) return $this->files; } } . */ /** * Produce license files using Zeng Guard. * The task can produce a license file from the given * license properties or it can use a template. * * @author Petr Rybak * @version $Id: 2e1e3730b96f5d5ea32d54fda8d9333b34eeaaba $ * @package phing.tasks.ext.zendguard * @since 2.4.3 */ class ZendGuardLicenseTask extends Task { protected $zendsignCommand; private $tmpLicensePath; /** * TASK PROPERTIES * * See http://static.zend.com/topics/Zend-Guard-User-Guidev5x.pdf * for more information on how to use ZendGuard * */ /** * Path to Zend Guard zendenc_sign executable * * @var string */ protected $zendsignPath; /** * Path to private key that will be used to sign the license * * @var string */ protected $privateKeyPath; /** * Where to store the signed license file * * @var string */ protected $outputFile; /** * Path to license template. If specified all * license properties will be ignored and the * template will be used to generate the file. * * @var string */ protected $licenseTemplate; /** * The name assigned to Product. This must be the same name used when encoding * the PHP files. * * REQUIRED * * @var string */ protected $productName; /** * The Name of the Registered owner of the license. * * REQUIRED * * @var string */ protected $registeredTo; /** * Expiration date of the license. Used if the license is issued with a date restriction. * Possible values: * - 'Never', '0' or false: the license won't expire * - A Date in format DD-MM-YYYY to set expiration for that date * - Relative date supported by the PHP strtotime function (e.g. +1 month) * * REQUIRED * * @var string */ protected $expires; /** * Limits the use of the license to IP addresses that fall within specification. Supports * wildcards for any of the IP place holders, as well as the two types of net masks * (filters). * Netmask pair An IP a.b.c.d, and a netmask w.x.y.z. (That is., 10.1.0.0/255.255.0.0), * where the binary of mask is applied to filter IP addresses. * ip/nnn (similar to a CIDR specification) This mask consists of nnn high-order 1 bits. * (That is, 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0). Instead of spelling out * the bits of the subnet mask, this mask notation is simply listed as the number of 1s * bits that start the mask. Rather than writing the address and subnet mask as * 192.60.128.0/255.255.252.0 the network address would be written simply as: * 192.60.128.0/22 which indicates starting address of the network and number of 1s * bits (22) in the network portion of the address. The mask in binary is * (11111111.11111111.11111100.00000000). * * OPTIONAL * * Example (Wildcard): * IP-Range = 10.1.*.* * Example (Net Mask): * IP-Range = 10.1.0.0/255.255.0.0 * Example (Net Mask): * IP-Range = 10.1.0.0/16 * * @var string */ protected $ipRange; /** * Coded string (Zend Host ID) used to lock the license to a specific hardware. The * Zend Host ID obtained from the machine where the encoded files and license are * to be installed. The Zend Host ID code can be obtained by using the zendid utility. * For more details, see Getting the Zend Host ID. * * REQUIRED if Hardware-Locked is set equal to YES. * Meaningless if Hardware-Locked is set equal to NO. * * User semicolon to enter more than one Host-ID * * Example: * Host-ID = H:MFM43-Q9CXC-B9EDX-GWYSU;H:MFM43-Q9CXC-B9EDX-GWYTY * * @var string */ protected $hostID; /** * Option that indicates if the license will be locked to a specific machine * using the Zend Host ID code(s). If set to YES, the Host-ID is required. * * OPTIONAL * * @var bool */ protected $hardwareLocked; /** * Semi-colon separated user defined values that will be part of the license. These values * CANNOT be modified after the license is produced. Modification * would invalidate the license. * * OPTIONAL * Example: * Tea=Mint Flavor;Coffee=Arabica * * @var string */ protected $userDefinedValues; /** * Semi-colon separated user defined x-values that will be part of the license. These values * CAN be modified after the license is produced. Modification * won't invalidate the license. * * OPTIONAL * Example: * Tea=Mint Flavor;Coffee=Arabica * * @var string */ protected $xUserDefinedValues; /** * @param $value */ public function setLicenseTemplate($value) { $this->licenseTemplate = $value; } /** * @param $productName */ public function setProductName($productName) { $this->productName = $productName; } /** * @param $registeredTo */ public function setRegisteredTo($registeredTo) { $this->registeredTo = $registeredTo; } /** * Process the expires property. If the value is * empty (false, '', ...) it will set the value to 'Never' * Otherwise it will run the value through strtotime so relative * date and time notation can be used (e.g. +1 month) * * @param mixed $expires * * @throws BuildException * @return string */ public function setExpires($expires) { // process the expires value if (false === $expires || '0' === $expires || strtolower($expires) == 'never' || '' === $expires) { $this->expires = 'Never'; } else { $time = strtotime($expires); if (!$time) { throw new BuildException("Unsupported expires format: " . $expires); } $this->expires = date('d-M-Y', $time); } } /** * @param $iprange */ public function setIpRange($iprange) { $this->ipRange = $iprange; } /** * @param $hostID */ public function setHostID($hostID) { $this->hostID = $hostID; } /** * @param $hardwareLocked */ public function setHardwareLocked($hardwareLocked) { $this->hardwareLocked = (bool) $hardwareLocked; } /** * @param $userDefinedValues */ public function setUserDefinedValues($userDefinedValues) { $this->userDefinedValues = $userDefinedValues; } /** * @param $xUserDefinedValues */ public function setXUserDefinedValues($xUserDefinedValues) { $this->xUserDefinedValues = $xUserDefinedValues; } /** * @param $zendsignPath */ public function setZendsignPath($zendsignPath) { $this->zendsignPath = $zendsignPath; } /** * @param $privateKeyPath */ public function setPrivateKeyPath($privateKeyPath) { $this->privateKeyPath = $privateKeyPath; } /** * @param $outputFile */ public function setOutputFile($outputFile) { $this->outputFile = $outputFile; } /** * Verifies that the configuration is correct * * @throws BuildException */ protected function verifyConfiguration() { // Check that the zend encoder path is specified if (empty($this->zendsignPath)) { throw new BuildException("Zendenc_sign path must be specified"); } // verify that the zend encoder binary exists if (!file_exists($this->zendsignPath)) { throw new BuildException("Zendenc_sign not found on path " . $this->zendsignPath); } // verify that the private key path is defined if (empty($this->privateKeyPath)) { throw new BuildException("You must define privateKeyPath."); } // verify that the private key file is readable if (!is_readable($this->privateKeyPath)) { throw new BuildException("Private key file is not readable: " . $this->privateKeyPath); } // if template is passed, verify that it is readable if (!empty($this->licenseTemplate)) { if (!is_readable($this->licenseTemplate)) { throw new BuildException("License template file is not readable " . $this->licenseTemplate); } } // check that output file path is defined if (empty($this->outputFile)) { throw new BuildException("Path where to store the result file needs to be defined in outputFile property"); } // if license template is NOT provided check that all required parameters are defined if (empty($this->licenseTemplate)) { // check productName if (empty($this->productName)) { throw new BuildException("Property must be defined: productName"); } // check expires if (null === $this->expires) { throw new BuildException("Property must be defined: expires"); } // check registeredTo if (empty($this->registeredTo)) { throw new BuildException("Property must be defined: registeredTo"); } // check hardwareLocked if (null === $this->hardwareLocked) { throw new BuildException("Property must be defined: hardwareLocked"); } // if hardwareLocked is set to true, check that Host-ID is set if ($this->hardwareLocked) { if (empty($this->hostID)) { throw new BuildException("If you set hardwareLocked to true hostID must be provided"); } } } } /** * Do the work * * @throws BuildException */ public function main() { try { $this->verifyConfiguration(); $this->generateLicense(); } catch (Exception $e) { // remove the license temp file if it was created $this->cleanupTmpFiles(); throw $e; } $this->cleanupTmpFiles(); } /** * If temporary license file was created during the process * this will remove it * * @return void */ private function cleanupTmpFiles() { if (!empty($this->tmpLicensePath) && file_exists($this->tmpLicensePath)) { $this->log("Deleting temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); unlink($this->tmpLicensePath); } } /** * Prepares and returns the command that will be * used to create the license. * * @return string */ protected function prepareSignCommand() { $command = $this->zendsignPath; // add license path $command .= ' ' . $this->getLicenseTemplatePath(); // add result file path $command .= ' ' . $this->outputFile; // add key path $command .= ' ' . $this->privateKeyPath; $this->zendsignCommand = $command; return $command; } /** * Checks if the license template path is defined * and returns it. * If it the license template path is not defined * it will generate a temporary template file and * provide it as a template. * * @return string */ protected function getLicenseTemplatePath() { if (!empty($this->licenseTemplate)) { return $this->licenseTemplate; } else { return $this->generateLicenseTemplate(); } } /** * Creates the signed license at the defined output path * * @throws BuildException * @return void */ protected function generateLicense() { $command = $this->prepareSignCommand() . ' 2>&1'; $this->log('Creating license at ' . $this->outputFile); $this->log('Running: ' . $command, Project::MSG_VERBOSE); $tmp = exec($command, $output, $return_var); // Check for exit value 1. Zendenc_sign command for some reason // returns 0 in case of failure and 1 in case of success... if ($return_var !== 1) { throw new BuildException("Creating license failed. \n\nZendenc_sign msg:\n" . join("\n", $output) . "\n\n"); } } /** * It will generate a temporary license template * based on the properties defined. * * @throws BuildException * @return string Path of the temporary license template file */ protected function generateLicenseTemplate() { $this->tmpLicensePath = tempnam(sys_get_temp_dir(), 'zendlicense'); $this->log("Creating temporary license template " . $this->tmpLicensePath, Project::MSG_VERBOSE); if (file_put_contents($this->tmpLicensePath, $this->generateLicenseTemplateContent()) === false) { throw new BuildException("Unable to create temporary template license file: " . $this->tmpLicensePath); } return $this->tmpLicensePath; } /** * Generates license template content based * on the defined parameters * * @return string */ protected function generateLicenseTemplateContent() { $contentArr = array(); // Product Name $contentArr[] = array('Product-Name', $this->productName); // Registered to $contentArr[] = array('Registered-To', $this->registeredTo); // Hardware locked $contentArr[] = array('Hardware-Locked', ($this->hardwareLocked ? 'Yes' : 'No')); // Expires $contentArr[] = array('Expires', $this->expires); // IP-Range if (!empty($this->ipRange)) { $contentArr[] = array('IP-Range', $this->ipRange); } // Host-ID if (!empty($this->hostID)) { foreach (explode(';', $this->hostID) as $hostID) { $contentArr[] = array('Host-ID', $hostID); } } else { $contentArr[] = array('Host-ID', 'Not-Locked'); } // parse user defined fields if (!empty($this->userDefinedValues)) { $this->parseAndAddUserDefinedValues($this->userDefinedValues, $contentArr); } // parse user defined x-fields if (!empty($this->xUserDefinedValues)) { $this->parseAndAddUserDefinedValues($this->xUserDefinedValues, $contentArr, 'X-'); } // merge all the values $content = ''; foreach ($contentArr as $valuePair) { list($key, $value) = $valuePair; $content .= $key . " = " . $value . "\n"; } return $content; } /** * Parse the given string in format like key1=value1;key2=value2;... and * converts it to array * (key1=>value1, key2=value2, ...) * * @param string $valueString Semi-colon separated value pairs * @param array $valueArray Array to which the values will be added * @param string $keyPrefix Prefix to use when adding the key * * @param string $pairSeparator * @return void */ protected function parseAndAddUserDefinedValues( $valueString, array &$valueArray, $keyPrefix = '', $pairSeparator = ';' ) { // explode the valueString (semicolon) $valuePairs = explode($pairSeparator, $valueString); if (!empty($valuePairs)) { foreach ($valuePairs as $valuePair) { list($key, $value) = explode('=', $valuePair, 2); // add pair into the valueArray $valueArray[] = array($keyPrefix . $key, $value); } } } } . */ require_once 'phing/Task.php'; /** * Class ZendServerDeploymentToolTask * * @author Siad Ardroumli * @package phing.tasks.ext.zendserverdevelopmenttools */ abstract class zsdtBaseTask extends Task { protected $action; protected $arguments = ''; /** @var string $descriptor */ protected $descriptor; /** @var string $schema */ protected $schema; /** @var array $path */ private $path = array( 'NIX' => '/usr/local/zend/bin/zdpack', 'WIN' => 'C:\Program Files (x86)\Zend\ZendServer\bin\zdpack', 'USR' => '' ); /** * The package descriptor file. * * @param string $descriptor * * @return void */ public function setDescriptor($descriptor) { $this->descriptor = escapeshellarg($descriptor); } /** * The path to the package descriptor schema used for validation. * * @param string $schema * * @return void */ public function setSchema($schema) { $this->schema = escapeshellarg($schema); } /** * @param string $path * * @return void */ public function setPath($path) { $this->path['USR'] = $path; } /** * {@inheritdoc} */ public function main() { $this->validate(); $command = ''; if ($this->path['USR'] !== '') { $command .= $this->path['USR']; } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $command .= escapeshellarg($this->path['WIN']); } else { $command .= $this->path['NIX']; } $commandString = sprintf('%s %s %s', $command, $this->action, $this->arguments); $msg = exec($commandString . ' 2>&1', $output, $code); if ($code !== 0) { throw new BuildException("Build package failed. \n Msg: " . $msg . " \n Pack command: " . $commandString); } } /** * Validates argument list. * * @return void */ protected function validate() { if ($this->schema !== null) { $this->arguments .= "--schema=$this->schema "; } } } . */ require_once 'phing/tasks/ext/zendserverdeploymenttool/zsdtBaseTask.php'; /** * Class ZendServerDeploymentToolTask * * @author Siad Ardroumli * @package phing.tasks.ext.zendserverdevelopmenttools */ class zsdtValidateTask extends zsdtBaseTask { /** * @inheritdoc} * * @return void */ public function init() { $this->action = 'validate'; } /** * {@inheritdoc} * * @throws BuildException * * @return void */ protected function validate() { parent::validate(); if ($this->descriptor === null) { throw new BuildException('The package descriptor file have to be set.'); } $this->arguments .= $this->descriptor; } } . */ require_once 'phing/tasks/ext/zendserverdeploymenttool/zsdtBaseTask.php'; /** * Class ZendServerDeploymentToolTask * * @author Siad Ardroumli * @package phing.tasks.ext.zendserverdevelopmenttools */ class zsdtPackTask extends zsdtBaseTask { /** @var string $package */ private $package; /** @var string $source */ private $source; /** @var string $scripts */ private $scripts; /** @var string $output */ private $output; /** @var string $phpbin */ private $phpbin; /** @var bool $lint */ private $lint = false; /** * A directory containing the data and the script directories, in addition to the package descriptor file. * * @param string $package * * @return void */ public function setPackage($package) { $this->package = escapeshellarg($package); } /** * Performs a PHP lint test on the deployment scripts before creating the package. * * @param boolean $lint * * @return void */ public function setLint($lint) { $this->lint = $lint; } /** * The directory in which the package is created. * The package name will be created as "-.zpk". * * @param string $output * * @return void */ public function setOutput($output) { $this->output = escapeshellarg($output); } /** * The PHP executable to use for lint. * * @param string $phpbin * * @return void */ public function setPhpbin($phpbin) { $this->phpbin = escapeshellarg($phpbin); } /** * The directory which contains the package deployment scripts. * The Deployment Tool will search this directory for the expected files and then packs them. * * @param string $scripts * * @return void */ public function setScripts($scripts) { $this->scripts = escapeshellarg($scripts); } /** * The directory that contains the application resources (PHP sources, JavaScript, etc.). * The directory's internal structure must match the necessary structure for the application to be functional. * * @param string $source * * @return void */ public function setSource($source) { $this->source = escapeshellarg($source); } /** * {@inheritdoc} * * @return void */ public function init() { $this->action = 'pack'; } /** * {@inheritdoc} * * @return void * * @throws BuildException */ protected function validate() { if ($this->descriptor === null || $this->scripts === null || $this->package === null) { throw new BuildException( 'The deployment tool needs at least the project descriptor, ' . 'the scripts folder and package folder to be set.' ); } elseif ($this->lint !== false && $this->phpbin === null) { throw new BuildException('You set the lint option but not the path to the php executable.'); } parent::validate(); if ($this->lint !== false) { $this->arguments .= '--lint '; } if ($this->source !== null) { $this->arguments .= "--src-dir=$this->source "; } if ($this->output !== null) { $this->arguments .= "--output-dir=$this->output "; } if ($this->phpbin !== null) { $this->arguments .= "--php-exe=$this->phpbin "; } $this->arguments .= "--scripts-dir=$this->scripts "; $this->arguments .= "--package-descriptor=$this->descriptor "; $this->arguments .= $this->package; } } . */ require_once 'phing/Task.php'; /** * A PHP code sniffer task. Checking the style of one or more PHP source files. * * @author Dirk Thomas * @version $Id: 1cb309b7992d03271825878803e5cabb757b9d63 $ * @package phing.tasks.ext */ class PhpCodeSnifferTask extends Task { /** * A php source code filename or directory * * @var PhingFile */ protected $file; // the source file (from xml attribute) /** * All fileset objects assigned to this task * * @var FileSet[] */ protected $filesets = array(); // all fileset objects assigned to this task // parameters for php code sniffer protected $standards = array('Generic'); protected $sniffs = array(); protected $showWarnings = true; protected $showSources = false; protected $reportWidth = 80; protected $verbosity = 0; protected $tabWidth = 0; protected $allowedFileExtensions = array('php', 'inc', 'js', 'css'); protected $allowedTypes = array(); protected $ignorePatterns = false; protected $noSubdirectories = false; protected $configData = array(); protected $encoding = 'iso-8859-1'; // parameters to customize output protected $showSniffs = false; protected $format = 'full'; /** * @var PhpCodeSnifferTask_FormatterElement[] */ protected $formatters = array(); /** * Holds the type of the doc generator * * @var string */ protected $docGenerator = ''; /** * Holds the outfile for the documentation * * @var PhingFile */ protected $docFile = null; private $haltonerror = false; private $haltonwarning = false; private $skipversioncheck = false; private $propertyName = null; /** * Cache data storage * @var DataStore */ protected $cache; /** * Load the necessary environment for running PHP_CodeSniffer. * * @return void */ public function init() { } /** * File to be performed syntax check on * @param PhingFile $file */ public function setFile(PhingFile $file) { $this->file = $file; } /** * Nested adder, adds a set of files (nested fileset attribute). * * @param FileSet $fs * @return void */ public function addFileSet(FileSet $fs) { $this->filesets[] = $fs; } /** * Sets the coding standard to test for * * @param string $standards The coding standards * * @return void */ public function setStandard($standards) { $this->standards = array(); $token = ' ,;'; $ext = strtok($standards, $token); while ($ext !== false) { $this->standards[] = $ext; $ext = strtok($token); } } /** * Sets the sniffs which the standard should be restricted to * @param string $sniffs */ public function setSniffs($sniffs) { $token = ' ,;'; $sniff = strtok($sniffs, $token); while ($sniff !== false) { $this->sniffs[] = $sniff; $sniff = strtok($token); } } /** * Sets the type of the doc generator * * @param string $generator HTML or Text * * @return void */ public function setDocGenerator($generator) { $this->docGenerator = $generator; } /** * Sets the outfile for the documentation * * @param PhingFile $file The outfile for the doc * * @return void */ public function setDocFile(PhingFile $file) { $this->docFile = $file; } /** * Sets the flag if warnings should be shown * @param boolean $show */ public function setShowWarnings($show) { $this->showWarnings = StringHelper::booleanValue($show); } /** * Sets the flag if sources should be shown * * @param boolean $show Whether to show sources or not * * @return void */ public function setShowSources($show) { $this->showSources = StringHelper::booleanValue($show); } /** * Sets the width of the report * * @param int $width How wide the screen reports should be. * * @return void */ public function setReportWidth($width) { $this->reportWidth = (int) $width; } /** * Sets the verbosity level * @param int $level */ public function setVerbosity($level) { $this->verbosity = (int) $level; } /** * Sets the tab width to replace tabs with spaces * @param int $width */ public function setTabWidth($width) { $this->tabWidth = (int) $width; } /** * Sets file encoding * @param string $encoding */ public function setEncoding($encoding) { $this->encoding = $encoding; } /** * Sets the allowed file extensions when using directories instead of specific files * @param array $extensions */ public function setAllowedFileExtensions($extensions) { $this->allowedFileExtensions = array(); $token = ' ,;'; $ext = strtok($extensions, $token); while ($ext !== false) { $this->allowedFileExtensions[] = $ext; $ext = strtok($token); } } /** * Sets the allowed types for the PHP_CodeSniffer::suggestType() * @param array $types */ public function setAllowedTypes($types) { $this->allowedTypes = array(); $token = ' ,;'; $type = strtok($types, $token); while ($type !== false) { $this->allowedTypes[] = $type; $type = strtok($token); } } /** * Sets the ignore patterns to skip files when using directories instead of specific files * @param $patterns * @internal param array $extensions */ public function setIgnorePatterns($patterns) { $this->ignorePatterns = array(); $token = ' ,;'; $pattern = strtok($patterns, $token); while ($pattern !== false) { $this->ignorePatterns[$pattern] = 'relative'; $pattern = strtok($token); } } /** * Sets the flag if subdirectories should be skipped * @param boolean $subdirectories */ public function setNoSubdirectories($subdirectories) { $this->noSubdirectories = StringHelper::booleanValue($subdirectories); } /** * Creates a config parameter for this task * * @return Parameter The created parameter */ public function createConfig() { $num = array_push($this->configData, new Parameter()); return $this->configData[$num - 1]; } /** * Sets the flag if the used sniffs should be listed * @param boolean $show */ public function setShowSniffs($show) { $this->showSniffs = StringHelper::booleanValue($show); } /** * Sets the output format * @param string $format */ public function setFormat($format) { $this->format = $format; } /** * Create object for nested formatter element. * @return PhpCodeSnifferTask_FormatterElement */ public function createFormatter() { $num = array_push( $this->formatters, new PhpCodeSnifferTask_FormatterElement() ); return $this->formatters[$num - 1]; } /** * Sets the haltonerror flag * @param boolean $value */ public function setHaltonerror($value) { $this->haltonerror = $value; } /** * Sets the haltonwarning flag * @param boolean $value */ public function setHaltonwarning($value) { $this->haltonwarning = $value; } /** * Sets the skipversioncheck flag * @param boolean $value */ public function setSkipVersionCheck($value) { $this->skipversioncheck = $value; } /** * Sets the name of the property to use * @param $propertyName */ public function setPropertyName($propertyName) { $this->propertyName = $propertyName; } /** * Returns the name of the property to use */ public function getPropertyName() { return $this->propertyName; } /** * Whether to store last-modified times in cache * * @param PhingFile $file */ public function setCacheFile(PhingFile $file) { $this->cache = new DataStore($file); } /** * Return the list of files to parse * * @return string[] list of absolute files to parse */ protected function getFilesToParse() { $filesToParse = array(); if ($this->file instanceof PhingFile) { $filesToParse[] = $this->file->getPath(); } else { // append any files in filesets foreach ($this->filesets as $fs) { $dir = $fs->getDir($this->project)->getAbsolutePath(); foreach ($fs->getDirectoryScanner($this->project)->getIncludedFiles() as $filename) { $fileAbsolutePath = $dir . DIRECTORY_SEPARATOR . $filename; if ($this->cache) { $lastMTime = $this->cache->get($fileAbsolutePath); $currentMTime = filemtime($fileAbsolutePath); if ($lastMTime >= $currentMTime) { continue; } else { $this->cache->put($fileAbsolutePath, $currentMTime); } } $filesToParse[] = $fileAbsolutePath; } } } return $filesToParse; } /** * Executes PHP code sniffer against PhingFile or a FileSet */ public function main() { if (!class_exists('PHP_CodeSniffer')) { @include_once 'PHP/CodeSniffer.php'; if (!class_exists('PHP_CodeSniffer')) { throw new BuildException("This task requires the PHP_CodeSniffer package installed and available on the include path", $this->getLocation( )); } } /** * Determine PHP_CodeSniffer version number */ if (!$this->skipversioncheck) { if (defined('PHP_CodeSniffer::VERSION')) { preg_match('/\d\.\d\.\d/', PHP_CodeSniffer::VERSION, $version); } else { preg_match('/\d\.\d\.\d/', shell_exec('phpcs --version'), $version); } if (version_compare($version[0], '1.2.2') < 0) { throw new BuildException( 'PhpCodeSnifferTask requires PHP_CodeSniffer version >= 1.2.2', $this->getLocation() ); } } if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException("Missing either a nested fileset or attribute 'file' set"); } if (count($this->formatters) == 0) { // turn legacy format attribute into formatter $fmt = new PhpCodeSnifferTask_FormatterElement(); $fmt->setType($this->format); $fmt->setUseFile(false); $this->formatters[] = $fmt; } $fileList = $this->getFilesToParse(); $cwd = getcwd(); // Save command line arguments because it confuses PHPCS (version 1.3.0) $oldArgs = $_SERVER['argv']; $_SERVER['argv'] = array(); $_SERVER['argc'] = 0; include_once 'phing/tasks/ext/phpcs/PhpCodeSnifferTask_Wrapper.php'; $codeSniffer = new PhpCodeSnifferTask_Wrapper($this->verbosity, $this->tabWidth, $this->encoding); $codeSniffer->setAllowedFileExtensions($this->allowedFileExtensions); if ($this->allowedTypes) { PhpCodeSnifferTask_Wrapper::$allowedTypes = $this->allowedTypes; } if (is_array($this->ignorePatterns)) { $codeSniffer->setIgnorePatterns($this->ignorePatterns); } foreach ($this->configData as $configData) { $codeSniffer->setConfigData($configData->getName(), $configData->getValue(), true); } /* * Verifying if standard is installed only after setting config data. * Custom standard paths could be provided via installed_paths config parameter. */ foreach($this->standards as $standard) { if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { // They didn't select a valid coding standard, so help them // out by letting them know which standards are installed. $installedStandards = PHP_CodeSniffer::getInstalledStandards(); $numStandards = count($installedStandards); $errMsg = ''; if ($numStandards === 0) { $errMsg = 'No coding standards are installed.'; } else { $lastStandard = array_pop($installedStandards); if ($numStandards === 1) { $errMsg = 'The only coding standard installed is ' . $lastStandard; } else { $standardList = implode(', ', $installedStandards); $standardList .= ' and ' . $lastStandard; $errMsg = 'The installed coding standards are ' . $standardList; } } throw new BuildException( 'ERROR: the "' . $standard . '" coding standard is not installed. ' . $errMsg, $this->getLocation() ); } } if (!$this->showWarnings) { $codeSniffer->cli->warningSeverity = 0; } // nasty integration hack $values = $codeSniffer->cli->getDefaults(); $_SERVER['argv'] = array('t'); $_SERVER['argc'] = 1; foreach ($this->formatters as $fe) { if ($fe->getUseFile()) { $_SERVER['argv'][] = '--report-' . $fe->getType() . '=' . $fe->getOutfile(); } else { $_SERVER['argv'][] = '--report-' . $fe->getType(); } $_SERVER['argc']++; } if ($this->cache) { require_once 'phing/tasks/ext/phpcs/Reports_PhingRemoveFromCache.php'; PHP_CodeSniffer_Reports_PhingRemoveFromCache::setCache($this->cache); // add a fake report to remove from cache $_SERVER['argv'][] = '--report-phingRemoveFromCache='; $_SERVER['argc']++; } $codeSniffer->process($fileList, $this->standards, $this->sniffs, $this->noSubdirectories); $_SERVER['argv'] = array(); $_SERVER['argc'] = 0; if ($this->cache) { PHP_CodeSniffer_Reports_PhingRemoveFromCache::setCache(null); $this->cache->commit(); } $this->printErrorReport($codeSniffer); // generate the documentation if ($this->docGenerator !== '' && $this->docFile !== null) { ob_start(); $codeSniffer->generateDocs($this->standards, $this->sniffs, $this->docGenerator); $output = ob_get_contents(); ob_end_clean(); // write to file $outputFile = $this->docFile->getPath(); $check = file_put_contents($outputFile, $output); if ($check === false) { throw new BuildException('Error writing doc to ' . $outputFile); } } elseif ($this->docGenerator !== '' && $this->docFile === null) { $codeSniffer->generateDocs($this->standards, $this->sniffs, $this->docGenerator); } if ($this->haltonerror && $codeSniffer->reporting->totalErrors > 0) { throw new BuildException('phpcodesniffer detected ' . $codeSniffer->reporting->totalErrors . ' error' . ($codeSniffer->reporting->totalErrors > 1 ? 's' : '')); } if ($this->haltonwarning && $codeSniffer->reporting->totalWarnings > 0) { throw new BuildException('phpcodesniffer detected ' . $codeSniffer->reporting->totalWarnings . ' warning' . ($codeSniffer->reporting->totalWarnings > 1 ? 's' : '')); } $_SERVER['argv'] = $oldArgs; $_SERVER['argc'] = count($oldArgs); chdir($cwd); } /** * Prints the error report. * * @param PHP_CodeSniffer $phpcs The PHP_CodeSniffer object containing * the errors. */ protected function printErrorReport($phpcs) { $sniffs = $phpcs->getSniffs(); $sniffStr = ''; foreach ($sniffs as $sniff) { if (is_string($sniff)) { $sniffStr .= '- ' . $sniff . PHP_EOL; } else { $sniffStr .= '- ' . get_class($sniff) . PHP_EOL; } } $this->project->setProperty($this->getPropertyName(), (string) $sniffStr); if ($this->showSniffs) { $this->log('The list of used sniffs (#' . count($sniffs) . '): ' . PHP_EOL . $sniffStr, Project::MSG_INFO); } // process output $reporting = $phpcs->reporting; foreach ($this->formatters as $fe) { $reportFile = null; if ($fe->getUseFile()) { $reportFile = $fe->getOutfile(); //ob_start(); } // Crude check, but they broke backwards compatibility // with a minor version release. if (PHP_CodeSniffer::VERSION >= '2.2.0') { $cliValues = array('colors' => false); $reporting->printReport($fe->getType(), $this->showSources, $cliValues, $reportFile, $this->reportWidth); } else { $reporting->printReport($fe->getType(), $this->showSources, $reportFile, $this->reportWidth); } // reporting class uses ob_end_flush(), but we don't want // an output if we use a file if ($fe->getUseFile()) { //ob_end_clean(); } } } /** * Outputs the results with a custom format * * @param array $report Packaged list of all errors in each file */ protected function outputCustomFormat($report) { $files = $report['files']; foreach ($files as $file => $attributes) { $errors = $attributes['errors']; $warnings = $attributes['warnings']; $messages = $attributes['messages']; if ($errors > 0) { $this->log( $file . ': ' . $errors . ' error' . ($errors > 1 ? 's' : '') . ' detected', Project::MSG_ERR ); $this->outputCustomFormatMessages($messages, 'ERROR'); } else { $this->log($file . ': No syntax errors detected', Project::MSG_VERBOSE); } if ($warnings > 0) { $this->log( $file . ': ' . $warnings . ' warning' . ($warnings > 1 ? 's' : '') . ' detected', Project::MSG_WARN ); $this->outputCustomFormatMessages($messages, 'WARNING'); } } $totalErrors = $report['totals']['errors']; $totalWarnings = $report['totals']['warnings']; $this->log(count($files) . ' files were checked', Project::MSG_INFO); if ($totalErrors > 0) { $this->log($totalErrors . ' error' . ($totalErrors > 1 ? 's' : '') . ' detected', Project::MSG_ERR); } else { $this->log('No syntax errors detected', Project::MSG_INFO); } if ($totalWarnings > 0) { $this->log($totalWarnings . ' warning' . ($totalWarnings > 1 ? 's' : '') . ' detected', Project::MSG_INFO); } } /** * Outputs the messages of a specific type for one file * @param array $messages * @param string $type */ protected function outputCustomFormatMessages($messages, $type) { foreach ($messages as $line => $messagesPerLine) { foreach ($messagesPerLine as $column => $messagesPerColumn) { foreach ($messagesPerColumn as $message) { $msgType = $message['type']; if ($type == $msgType) { $logLevel = Project::MSG_INFO; if ($msgType == 'ERROR') { $logLevel = Project::MSG_ERR; } else { if ($msgType == 'WARNING') { $logLevel = Project::MSG_WARN; } } $text = $message['message']; $string = $msgType . ' in line ' . $line . ' column ' . $column . ': ' . $text; $this->log($string, $logLevel); } } } } } } //end phpCodeSnifferTask /** * @package phing.tasks.ext */ class PhpCodeSnifferTask_FormatterElement extends DataType { /** * Type of output to generate * @var string */ protected $type = ""; /** * Output to file? * @var bool */ protected $useFile = true; /** * Output file. * @var string */ protected $outfile = ""; /** * Validate config. */ public function parsingComplete() { if (empty($this->type)) { throw new BuildException("Format missing required 'type' attribute."); } if ($this->useFile && empty($this->outfile)) { throw new BuildException("Format requires 'outfile' attribute when 'useFile' is true."); } } /** * @param $type */ public function setType($type) { $this->type = $type; } /** * @return string */ public function getType() { return $this->type; } /** * @param $useFile */ public function setUseFile($useFile) { $this->useFile = $useFile; } /** * @return bool */ public function getUseFile() { return $this->useFile; } /** * @param $outfile */ public function setOutfile($outfile) { $this->outfile = $outfile; } /** * @return string */ public function getOutfile() { return $this->outfile; } } //end FormatterElement . */ require_once 'phing/tasks/ext/PearPackageTask.php'; /** * A task to create a PEAR package.xml version 2.0 file. * * This class uses the PEAR_PackageFileManager2 class to perform the work. * * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o * requiring changes to this class. We've accomplished this by having generic