Does PHP_CodeSniffer have an API I can use, rather than run the command line?
So given a string of PHP code, $code, and Composer ensuring loading of the PHP_CodeSniffer code, is there something I can do such as:
// Pseudocode!
$code_sniffer = new PHPCodeSniffer;
$result = $code_sniffer->sniff($code);
rather than go via the command line with something like:
$result = exec(sprintf('echo %s | vendor/bin/phpcs', escapeshellarg($code)));
There is, but you need to write more code than that.
Take a look at the example here: https://gist.github.com/gsherwood/aafd2c16631a8a872f0c4a23916962ac
That example allows you to sniff a piece of code that isn't written to a file yet, and set up things like the standard to use (could also be a ruleset.xml file).
Another example, that uses the JS tokenizer instead of PHP + pulls content from an existing file, is available here: https://gist.github.com/gsherwood/f17cfc90f14a9b29eeb6b2e99e6e7f66
It is shorter because it doesn't use as many options.
Here's what I got working for PHPCS 2:
PHP_CodeSniffer::setConfigData(
'installed_paths',
// The path to the standard I am using.
__DIR__ . '/../../vendor/drupal/coder/coder_sniffer',
TRUE
);
$phpcs = new PHP_CodeSniffer(
// Verbosity.
0,
// Tab width
0,
// Encoding.
'iso-8859-1',
// Interactive.
FALSE
);
$phpcs->initStandard('Drupal');
// Mock a PHP_CodeSniffer_CLI object, as the PHP_CodeSniffer object expects
// to have this and be able to retrieve settings from it.
// (I am using PHPCS within tests, so I have Prophecy available to do this. In another context, just creating a subclass of PHP_CodeSniffer_CLI set to return the right things would work too.)
$prophet = new \Prophecy\Prophet;
$prophecy = $prophet->prophesize();
$prophecy->willExtend(\PHP_CodeSniffer_CLI::class);
// No way to set these on the phpcs object.
$prophecy->getCommandLineValues()->willReturn([
'reports' => [
"full" => NULL,
],
"showSources" => false,
"reportWidth" => null,
"reportFile" => null
]);
$phpcs_cli = $prophecy->reveal();
// Have to set these properties, as they are read directly, e.g. by
// PHP_CodeSniffer_File::_addError()
$phpcs_cli->errorSeverity = 5;
$phpcs_cli->warningSeverity = 5;
// Set the CLI object on the PHP_CodeSniffer object.
$phpcs->setCli($phpcs_cli);
// Process the file with PHPCS.
$phpcsFile = $phpcs->processFile(NULL, $code);
$errors = $phpcsFile->getErrorCount();
$warnings = $phpcsFile->getWarningCount();
$total_error_count = ($phpcsFile->getErrorCount() + $phpcsFile->getWarningCount());
// Get the reporting to process the errors.
$this->reporting = new \PHP_CodeSniffer_Reporting();
$reportClass = $this->reporting->factory('full');
// This gets you an array of all the messages which you can easily work over.
$reportData = $this->reporting->prepareFileReport($phpcsFile);
// This formats the report, but prints it directly.
$reportClass->generateFileReport($reportData, $phpcsFile);
Related
I'm brand new to phpunit and attempting to write a test that asserts that three notes were created, but I'm getting all of the notes from the DB.
/** #test */
public function it_gets_notes()
{
$address = Address::first();
$notes = factory(AddressNote::class, 3)->create(['address_id'
=> $address->id]);
$found = $this->notesClass->getData(['address_id' => $address-
>id]);
$this->assertCount(3, $found);
}
}
The Address and AddressNote models are working properly. I think I'm most confused about the getData method, which I know I need for my code coverage. Anyone see what I'm missing that would generate the error in the title?
If you need to check the difference after running your create method, then save $found before and after adding them, and the subtraction will be your number:
public function it_gets_notes()
{
$address = Address::first();
$found = $this->notesClass->getData(['address_id' => $address->id]);
$notes = factory(AddressNote::class, 3)->create(['address_id' => $address->id]);
$foundAfter = $this->notesClass->getData(['address_id' => $address->id]);
$difference = count($foundAfter) - count($found);
$this->assertEquals(3, $difference);
}
Note that you need to use assertEquals() with 3 and the difference now instead of assertCount(), since you're comparing numbers.
I don't know the whole your story, but I assume that your first mistake was that you did not create a testing database.
So, that would be the first step - in addition to your databaseName (whatever the name) create a databaseName_test.
There are some other steps to do - in your ,env file change the name of the databaseName to databaseName_testing - but only while you're doing your testing (and then immediately rollback to your original databaseName).
Yet, the problem can still persist (PHP Unit is not a perfect tool, just like PHP), and here is the hack that can help.
Instead of:
$this->assertEquals(3, $difference);
write:
$this->assertEquals(11935, $difference); //the number is specific for your case
Yep, it's stupid, but it should work...
I'm trying to update a template document via PHP API using this: https://github.com/docusign/docusign-php-client/blob/master/src/Api/TemplatesApi.php#L4946
I get one of two errors depending on if I set the apply_document_fields option.
Without it set, I get UNSPECIFIED ERROR Value cannot be null.\r\nParameter name: fileBytes. However, if I view the request body before sending, document_base_64 is set as expected.
With apply_document_fields set 'true' (actual boolean value is not supported), I get FORMAT_CONVERSION_ERROR The data could not be converted.
Either way, it seems like the document data is not getting sent correctly, but I can't figure out how I'm supposed to be sending it. Here's my code:
public static function updateTemplateWithDocument(string $documentId, string $templateId, $documentBody = null)
{
$api = My_Service_Docusign::getInstance();
$templatesApi = new DocuSign\eSign\Api\TemplatesApi($api->getAuth());
$document = new \DocuSign\eSign\Model\Document();
$document->setDocumentBase64(base64_encode($documentBody));
// Got an error reusing $documentId, so I'm incrementing it now
$document->setDocumentId((string) (((int)$documentId) + 1));
$def = new DocuSign\eSign\Model\EnvelopeDefinition();
$def->setDocuments(array($document));
$opts = new \DocuSign\eSign\Api\TemplatesApi\UpdateDocumentOptions();
// Different behavior with this set vs not
$opts->setApplyDocumentFields('true');
$res = $tmpApi->updateDocument($api->getAccountId(), $documentId, $templateId, $def, $opts);
return $res;
}
Unfortunately, DocuSign support doesn't support their API :-(
I figured out I need to use TemplatesApi::updateDocuments (plural) instead, which also allows me to reuse the documentId.
Below is my Save Configuration file:
<?php
require_once 'Config/Lite.php';
$config = new Config_Lite();
$config->read('/var/www/html/svnmanager/Config/testing');
$config->set('/lol', 'user', 'JohnDoe')
->set('/lol', 'password', 'lemo')
->set('db2', 'user', '');
// set with ArrayAccess
$config['general'] = array('lang' => 'fr');
echo $config;
$config->save();
?>
and following is the output:
debug = ""
[db]
user = "JohnDoe"
password = "d0g1tcVs$HgIn1"
[db2]
user = ""
password = "d0g1tcVs$HgIn1"
[general]
lang = "fr"
[/lol]
user = "JohnDoe"
password = "ddada"
How do remove the double qoutes when saving the file?
for example:
[/lol]
user = JohnDoe
password = ddada
Add
$config->setQuoteStrings(false);
before saving it to the file
I'm going to start off with a rant: You are always better off using FLOSS libraries as intended/documented rather than hacking them to do what you want, if at all possible - even when the code is the only documentation available. For example, if a new version of Config_Lite comes out and you upgrade to that, you'll have "lost" your fixes.
(And, as if to prove my point, version 0.2.0 was released today at http://pear.php.net/package/Config_Lite/download/0.2.0)
To be more specific to answering your question, you need to call the setQuoteStrings method before you either explicitly save the .ini file output to a file using the write method or do anything that treats $config as a string value.
Typically, I'd do things in this order:
Create the [config] object first.
Set whatever options applicable (such as turning off quoted strings in this case)
Call whatever other methods as required (e.g. set values to sections etc)
Use resultant object (e.g. save the .ini file)
tl;dr:
$config = ....
$confg->setQuoteStrings(false);
$config->set(...);
echo $config;
$config->save();
Found myself a solution. You need to change the protected $quoteStrings = true; to protected $quoteStrings = false; in your Lite.php file :)
I use JasperServer and PHP JavaBridge to generate PDF reports via JasperServer inside PHP. I get compile error because of missing (unassigned) parameter passed to JRXML compiler
Fatal error: Uncaught [[o:Exception]:
"java.lang.Exception: Invoke failed:
[[c:JasperCompileManager]]->compileReport((o:String)[o:String]).
Cause: net.sf.jasperreports.engine.design.JRValidationException:
**Report design not valid** : 1. **Query parameter not found** : db_field_id VM:
1.6.0_18#http://java.sun.com/" at: #-12
net.sf.jasperreports.engine.design.JRAbstractCompiler.verifyDesign(JRAbstractCompiler.java:258)
I cant find a way to pass my
$params = new Java("java.util.HashMap");
foreach ($jrxml_params as $key => $jr_param) $params->put($key, $jr_param);
list of params to the compile method nor I can disable this verification by
$japser_props = new JavaClass("net.sf.jasperreports.engine.util.JRProperties");
$japser_props->COMPILER_XML_VALIDATION = false;
Here is what I use to generate PDF (works fine if JRXML file doesn't contain $P{} pamareters and halts otherwise)
$class = new JavaClass("java.lang.Class");
$class->forName("com.mysql.jdbc.Driver");
$driverManager = new JavaClass("java.sql.DriverManager");
$conn = $driverManager->getConnection("jdbc:mysql://localhost:3306/XXX?user=XXX&password=1234");
$compileManager = new JavaClass("net.sf.jasperreports.engine.JasperCompileManager");
$report = $compileManager->compileReport(realpath("/www/some.jrxml"));
$params = new Java("java.util.HashMap");
foreach ($jrxml_params as $key => $jr_param) $params->put($key, $jr_param);
$jasperPrint = $fillManager->fillReport($report, $params, $conn);
$exportManager = new JavaClass("net.sf.jasperreports.engine.JasperExportManager");
$outputPath = realpath(".")."/"."output.pdf";
$exportManager->exportReportToPdfFile($jasperPrint, $outputPath);
How do I avoid this error, I know what I need to pass and I don't know a way to do it, can't I just pass params to fillManager?
$japser_props = new JavaClass("net.sf.jasperreports.engine.util.JRProperties");
$japser_props->setProperty('net.sf.jasperreports.compiler.xml.validation',true);
this is the way to set property from PHP but that's not the problem. It turns out everything was fine, I've missed parameter declaration before my MySQL query... Put
<parameter name="db_field_id" class="java.lang.Integer">
in your JRXML before you use it as $P{db_field_id} now it compliles fine and later
$jasperPrint = $fillManager->fillReport($report, $params, $conn);
parameters are assigned at fill time
First let me say sorry for the amount of code I'm posting below I'm going to try and keep it as short as possible but this is built on top of my MVC (lightweight-mvc)
Ok So my Problem is that for some reason php is throwing a fatal error on code that should not be being used in my current code,
So how this works I have my MVC witch used the first 2 parts of the url to know what its loading, the problem is I'm building a Moulder CMS into my MVC so it's boot strapping twice,
So here is my Problem,
http://{domain}/admin/control/addon/uploader/method/uploadCheck/
I'm using the above now let me explain a little into that the /admin/control are for the main MVC System it auto-loads the Admin controller then fires the controlAction method from the controller much the same as most MVC's,
The next part are URL paramters that build an array the same as GET or POST would
array('addon'=>'uploader', 'method'=>'uploadCheck')
So from that my control action will auto load as is the code below
public function controlAction(){
global $_URL;
if(cleanData::URL("addon")){
$addonName = "addon_".cleanData::URL("addon");
$methodName = (cleanData::URL("method"))? cleanData::URL("method")."Action" : "indexAction";
echo $methodName;
$addon = new $addonName();
$addon->$methodName();
return;
}else{
$this->loadView("CMS/controll");
}
}
cleanData::URL is an abstract method that just returns the value of the key provided though addSlashes()
So as you can see from the code below it will then use the autoloader to load the module(AKA addon)
Just so you can follow the auto loader works in a simpler version of the Zend Frame work autoloader _ so you have class name addon_admin that would be inside file admin.php that is in the folder addon so the autoloader will load addon/admin.php
So As above with my URL and controlAction it's loading addon/uploader.php and as such this is the contents
<?php
class addon_uploader extends Addons{
public function uploadCheckAction(){
echo 0;
}
public function uploaderAction(){
if (!empty($_FILES)) {
$tmpFile = $_FILES['Filedata']["tmp_name"];
$newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']);
move_uploaded_file($tmpFileName, $newLock);
$POSTback = array(
'name' => $_FILES['Filedata']['name'],
'type' => $_FILES['Filedata']['type'],
'tmp_name' => $newLock,
'error' => $_FILES['Filedata']['error'],
'size' => $_FILES['Filedata']['size']
);
echo json_enocde($POSTback);
}
}
}
?>
But as you can see from my URL its using the uploadCheckAction method witch for debugging i have set so it always says false (AKA 0),
But i seem to get this error:
Fatal error: Only variables can be passed by reference in C:\xampp\htdocs\FallenFate\addon\uploader.php on line 11
But line 11 is $newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']); witch should not be being used could any one provide any help into why this would occur and how i could fix it
end() PHP Manual needs an expression of a single variable (more precisely an array), but not a function return value or any other type of expression.
I think that's basically the cause of your error, more specifically with your code:
$newLock = "../uploads/".end(explode('/', $tmpFile).$_FILES['Filedata']['name']);
you're even driving this far beyond any level of treatment PHP can cope with:
you concatenate an array with a string (which results in a string).
you run end() on that string - not on a variable, not even an array.
I have no clue what you try to do with the code, but I can try:
$filename = $_FILES['Filedata']['name'];
$parts = explode('/', $tmpFile);
$last = end($parts);
$newLock = "../uploads/". $last . $filename;
Or probably even only this:
$filename = $_FILES['Filedata']['name'];
$newLock = "../uploads/". $filename;