A Collection isn't Arrayable when testing - laravel

I'm making some HTTP Tests and I'm having an issue in one of them. Here's what happening:
Same endpoint
Same data on database
Same PHP version
Same headers
Different results
Here's the code:
1.
dd(
$interestResults instanceof Arrayable,
get_class($interestResults),
$interestResults[0] instanceof Arrayable,
get_class($interestResults[0]),
Arrayable::class,
phpversion()
);
2.
$typeBefore = gettype($interestResults);
$typeOfItemBefore = gettype($interestResults[0]);
$interestResults = $interestResults->toArray();
dd($typeBefore, $typeOfItemBefore, gettype($interestResults), gettype($interestResults[0]));
Here's what I get on Postman:
1.
true
"Illuminate\Database\Eloquent\Collection"
true
"App\Post"
"Illuminate\Contracts\Support\Arrayable"
"7.2.4"
2.
"object"
"object"
"array"
"array"
Here's what I get when testing:
1.
false
"Illuminate\Database\Eloquent\Collection"
true
"App\Post"
"Illuminate\Contracts\Support\Arrayable"
"7.2.4"
2.
"object"
"object"
"array"
"object"

TL;DR
If you use Laravel Valet, don't use your global phpunit. Use the project's local phpunit by running vendor/bin/phpunit.
Detailed version
While investigating this strange behavior I came to the conclusion that, since I know that class IS Illuminate\Database\Eloquent\Collection and it extends Illuminate\Support\Collection that implements Arrayable, it couldn't just "don't be" an instance of Arrayable.
So I've decided to check with Reflection what kind of Arrayable it was. That was my code:
$reflection = new \ReflectionClass(get_class($interestResults));
$implementedInterfacesList = array_keys($reflection->getInterfaces());
$isItArrayableByReflaction = in_array('Illuminate\Contracts\Support\Arrayable', $implementedInterfacesList);
$isItArrayableByInstanceOf = $interestResults instanceof \Illuminate\Contracts\Support\Arrayable;
dd($implementedInterfacesList, $isItArrayableByReflaction, $isItArrayableByInstanceOf);
And, for my surprise, those were the results:
Postman
array:8 [
0 => "JsonSerializable"
1 => "Illuminate\Contracts\Support\Jsonable"
2 => "Traversable"
3 => "IteratorAggregate"
4 => "Countable"
5 => "Illuminate\Contracts\Support\Arrayable"
6 => "ArrayAccess"
7 => "Illuminate\Contracts\Queue\QueueableCollection"
]
true
true
Terminal
array:8 [
0 => "JsonSerializable"
1 => "Tightenco\Collect\Contracts\Support\Jsonable"
2 => "Traversable"
3 => "IteratorAggregate"
4 => "Countable"
5 => "Tightenco\Collect\Contracts\Support\Arrayable"
6 => "ArrayAccess"
7 => "Illuminate\Contracts\Queue\QueueableCollection"
]
false
false
Interesting, Tightenco\Collect\Contracts\Support\Arrayable, but composer why tightenco\collect?
composer why tightenco/collect
[InvalidArgumentException]
Could not find package "tightenco/collect" in your project
So, the error isn't on my project neither on its dependencies. I've tried to run local local phpunit (vendor/bin/phpunit) and:
array:8 [
...
]
true
true
Great! Problem "fixed", but composer why was it happening?
composer global why tightenco/collect
Changed current directory to /Users/guilherme/.composer
laravel/valet v2.0.10 requires tightenco/collect (^5.3)
That's it! When running my global phpunit composer will use my global autoload and Laravel conflicts with tightenco/collect.
The solution?
Well, while I don't consider it a solution, I think this is the official one: Use the project's local phpunit by running vendor/bin/phpunit.
Also, you can skip tests that need Arrayable to be Illuminate\Contracts\Support\Arrayable:
use Illuminate\Contracts\Support\Arrayable;
...
if (!collect() instanceof Arrayable) {
$skipMessage = <<<'MESSAGE'
This test has conflicts with tightenco/collect and it seems you are using it.
If you are running the testsuite with your global phpunit, please try running 'vendor/bin/phpunit'.
MESSAGE;
$this->markTestSkipped($skipMessage);
}

Related

wkhtmltopdf, 0.12.6, Warning: Blocked access to file

When upgrade wkhtmltopdf to 0.12.6, it came to such messages and the image did not show in the target pdf:
Warning: Blocked access to file /path/to/bpa_product_layering.png
BTW, the same source html file works well with 0.12.5
This is caused by the change of default behavior in version 0.12.6 of wkhtmltopdf. wkhtmltopdf disables local file access by default now. It could be solved by adding the command line parameter
--enable-local-file-access
or the combination
--disable-local-file-access --allow <path>
For those that are using laravel-snappy, add the 'enable-local-file-access' option in the config\snappy.php:
'pdf' => [
'enabled' => true,
'binary' => env('WKHTML_PDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
'timeout' => false,
'options' => [
'enable-local-file-access' => true,
'orientation' => 'landscape',
'encoding' => 'UTF-8'
],
'env' => [],
],
'image' => [
'enabled' => true,
'binary' => env('WKHTML_IMG_BINARY', '/usr/local/bin/wkhtmltoimage'),
'timeout' => false,
'options' => [
'enable-local-file-access' => true,
'orientation' => 'landscape',
'encoding' => 'UTF-8'
],
'env' => [],
],
wkhtmltopdf disables local file access by default in the 0.12.6 version
Just bumping this thread with a correction in case you're still getting the same error in spite of using:
--enable-local-file-access
For some reason, this cmd line argument does not work when being specified after input/output files, you have to write this argument right after wkhtmltopdf.exe.
So
wkhtmltopdf.exe --enable-local-file-access input.html output.pdf
instead of other variants.
in my case, I put "enable-local-file-access": "", in options, it worked.
In Windows with Python, I came across a similar error as well when running code:
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries)
Error:
Warning: Blocked access to file C:/XXXXXX/background.A.jpg
Error: Failed to load about:blank, with network status code 301 and
http status code 0 - Protocol "about" is unknown
What I did to resolve this:
Add variable options
kitoptions = {
"enable-local-file-access": None
}
Add options to call
FROM
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries)
TO
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries, options=kitoptions)
Full Source:
import imgkit
#library path to kit
path_wkthmltopdf = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltoimage.exe'
wkhtmltoimage_binaries = imgkit.config(wkhtmltoimage=path_wkthmltopdf)
#OPTIONS
kitoptions = {
"enable-local-file-access": None
}
html_file_directory = r'C:\XXXX\template'
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries, options=kitoptions)
if result:
print("successful")
else:
print("failed")
For the C API, contrary to what the documentation says, it's not load.blockLocalFileAccess but loadPage.blockLocalFileAccess that you must set to "false":
wkhtmltoimage_set_global_setting(settings, "loadPage.blockLocalFileAccess", "false");
Hopefully, the documentation will be updated soon; see issue #4763.
I confirm that the problem comes from the wkhtmltopdf version. For those on Symfony (3.4), just add an option in config.yml:
knp_snappy:
pdf:
options:
enable-local-file-access: true
I know am a bit late in party but just wanted to write clear example with c# here so one can understand clearly.
ProcessStartInfo proc = new ProcessStartInfo();
proc = new ProcessStartInfo();
proc.RedirectStandardError = true;
proc.UseShellExecute = false;
proc.WorkingDirectory = #"" + Config.WkhtmltopdfPath;
proc.FileName = #"" + Config.WkhtmltopdfPath + #"\wkhtmltopdf.exe";
proc.Arguments = #" --enable-local-file-access -T 0 -B 0 --page-width 210mm --page-height 450mm " + fileName + ".html " + fileName + ".pdf";
Process inkscape = Process.Start(proc);

Mews\Purifier\Purifier::__construct() must be an instance of Illuminate\Filesystem\Filesystem

I installed Mews-Purifier on laravel 5.1
I used Froala Editor.
https://stackoverflow.com/
<script>asdfasdfasdf</script>
<iframe>qwerqwerqwer</iframe>
I expect result.
<p>https://stackoverflow.com/</p>
<p>qwerqwerqwer</p>
but, I am not see it.
when save it,
$data['detail'] = app('purifier')->clean($data['detail']);
if use Purifier::clean($data['detail']), It send error message me.
Non-static method Mews\Purifier\Purifier::clean() should not be called statically
so, It changed.
$data['detail'] = (new \Mews\Purifier\Purifier)->clean($data['detail']);
send error message too.
Type error: Too few arguments to function Mews\Purifier\Purifier::__construct(),
so I do changed.
(new Mews\Purifier\Purifier($data['detail'], ['AutoFormat.DisplayLinkURI' => true] ))->clean($data['detail');
Type error: Argument 1 passed to Mews\Purifier\Purifier::__construct() must be an instance of Illuminate\Filesystem\Filesystem, string given, called in
what Filesystem? what file??
Let me know How should I use it?
If I wasn't good at installing, what would it be?
Oh the installation did the following.
terminal
composer require mews/purifier
/config/app.php
'providers' => [
// ...
Mews\Purifier\PurifierServiceProvider::class,
],
'aliases' => [
// ...
'Purifier' => Mews\Purifier\Facades\Purifier::class,
]
terminal
php artisan vendor:publish
check created file. /config/purifier.php
Thanks for watching
Please let me know if you know.

Unable to mock Cache::put() facade in Laravel

I'm trying to mock the Cache::put() facade. But it gives me an error. I have tried different ways but couldn't figure it out.
public function testGetAllFromDatabase()
{
$industry = new Industry();
Cache::shouldReceive('has')
->once()
->with('industries.all')
->andReturn(false);
Cache::shouldReceive('put')
->with('industries.all', '', 0)
->andReturn(true);
$this->industryMock
->shouldReceive('all')
->once()
->andReturn(array_reverse($this->industries));
$this->app->instance(Industry::class, $this->industryMock);
$industryRepository = new IndustryRepository();
$all = $industryRepository->all();
dd($all);
$this->assertContains( $this->industries[2], $all);
}
But when I execute it the following error is occurring.
$ vendor/bin/phpunit
PHPUnit 7.2.7 by Sebastian Bergmann and contributors.
...E 4 / 4 (100%)
Time: 3.76 seconds, Memory: 12.00MB
There was 1 error:
1) Tests\Unit\RepositoriesTests\IndustryRepositoryTest::testGetAllFromDatabase
Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_1_Illuminate_Cache_CacheManager::put('industries.all', object(Illuminate\Database\Eloquent\Collection), '1440'). Either the method was unexpected or its arguments matched no expected argument list for this method
Objects: ( array (
'Illuminate\\Database\\Eloquent\\Collection' =>
array (
'class' => 'Illuminate\\Database\\Eloquent\\Collection',
'properties' =>
array (
),
),
))
F:\development\consulting.local\src\vendor\mockery\mockery\library\Mockery\ExpectationDirector.php:92
F:\development\consulting.local\src\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:223
F:\development\consulting.local\src\app\Repositories\IndustryRepository.php:30
F:\development\consulting.local\src\tests\Unit\RepositoriesTests\IndustryRepositoryTest.php:81
I have tried many ways but couldn't get it to fix. Thank you.
Since it may help others, Laravel's facade includes helper functions that allow swapping then with a Mockery test double
This means that when you use a shouldReceive you can chain it with any Mockery expectation for example in this case if you don't care about some parameters you can use:
Cache::shouldReceive('put')
->with('industries.all', \Mockery::any(), \Mockery::any())
->andReturn(true);
In case it helps others, it's good to point out that you may not want to mock Cache, but instead actually use the real Cache.
That's because it's a Cache for testing only:
When running tests via vendor/bin/phpunit, Laravel [....] automatically configures the session and cache to the array driver while testing, meaning no session or cache data will be persisted while testing.
https://laravel.com/docs/8.x/testing#environment
Note that unlike the OP's test, you may need to follow Laravel's guidance about your test class extending their TestCase to get the behavior, e.g.
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase

How to iterate over a string to construct nagios_service check as exported resource?

I wrote a custom fact, which returns a comma separated list of addr:port, like this:
sb_intl_conn => sbcms-t:22,sbsql05-wvuk-inst5:1434,sborc07-uk-t:1533,..,..,..
The number of elements in the string varies from node to node. I need to do a Nagios tcp-port-check on each of them. I think sb_intl_conn.split(",") will turn this string into an array and then how can I iterate over it to do something like this?
##nagios_service { "check_stat_${::fqdn}_${addr}_${port}":
use => 'generic-service',
check_command => "remote-nrpe-tcp-check!${addr}!${port}",
service_description => "V2::CON: ${addr} [Palms]",
display_name => "Connection check: ${addr}:${port}",
servicegroups => 'batch-worker',
hostgroup_name => 'batch-job',
}
Any help would be greatly appreciated. Cheers!!
Update: 1
I was tying to simulator iamauser's suggestion but not been able to get my head around it yet. This is what I did: in my foo.pp:
class test::foo {
define bar {
$var1 = inline_template("<%= scope.lookupvar($name).split(':').first.to_s.chomp %>")
$var2 = inline_template("<%= scope.lookupvar($name).split(':').last.to_s.chomp %>")
notify {"${var1}_${var2}": }
}
}
and then in my node.pp:
$ifs = ['abc.com:80','xyz.co.uk:1512']
test::foo::bar {$ifs:}
which throws in these error on the node:
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse inline template: Could not find value for 'abc' in 65 at /etc/puppet/services/test/manifests/foo.pp:4 on node jobserver-01.local.cloud.uk
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
Don't understand what I'm doing wrong. And why is Could not find value for 'abc'; not abc.com? Any idea?? Cheers!!
Update: 2
I ended up using heira and decided to give a try to the original "array of hashes" idea and having some problem implementing:
This is what I have in heira:
hiera -d -c /etc/puppet/hiera.yaml nag_chk m_env=talend s_env=local
[ ... ]
DEBUG: Thu Mar 21 12:28:02 +0000 2013: Got answer for key nagi_chk, final answer
DEBUG: Thu Mar 21 12:28:02 +0000 2013: Answer after outer loop = archimedes-db-02.svc.ft.com:1521 ftftp01-uvln-uk-p:22 www.google.com:80 ftaps01-lvpr-uk-local:8080
archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80
Then, in my foo.pp
class test::foo {
define bar2 () {
$var1 = $name['addr']
$var2 = $name['port']
notify {"*** ${var1}_${var2} *********": }
}
}
and my node.pp:
$array_chk = hiera('nag_chk')
$urls = inline_template("<%= '$array_chk'.split(' ').map{|kv| v1,v2 = kv.split(':'); {'addr' => v1, 'port' => v2}} -%>")
test::foo::bar2 {$urls:}
and as usual, I get an error:
err: Could not retrieve catalog from remote server: Error 400 on
SERVER: name is not an hash or array when accessing it with 0 at
/etc/puppet/services/talend/talend/manifests/foo.pp:10 on node
talend-jobserver-01.local.cloud.ft.com warning: Not using cache on
failed catalog err: Could not retrieve catalog; skipping run
What's am I doing wrong? As far as I can see, the "array of hash" in right format in the irb console:
irb(main):001:0> STRING = "archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80"
=> "archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80"
irb(main):003:0>
irb(main):002:0> STRING.split(' ').map{|kv| v1,v2 = kv.split(':'); {'addr' => v1, 'port' => v2}}
=> [{"addr"=>"archimedes-db-02", "port"=>"1521"}, {"addr"=>"ftftp01-uvln-uk-p", "port"=>"22"}, {"addr"=>"google.com", "port"=>"80"}]
any further thought(s)? Cheers!!
This example may help solve your particular case.
$foo = [{"addr" => "bar", "port" => "1"},
{"addr" => "bat", "port" => "2"}]
testmod::bar {$foo:}
define testmod::bar () {
$var1 = $name["addr"]
$var2 = $name["port"]
notify {"${var1}_${var2}": }
}
Put the nagios type inside the define type. You may have to change the csv to a hash.
UPDATE: Added after #MacUsers update. The following works for me :
$foo = ["abc.com:80","xyz.co.uk:1512"]
testmod::bar {$foo:}
define testmod::bar () {
$var1 = inline_template("<%= '$name'.split(':').first.to_s.chomp %>")
$var2 = inline_template("<%= '$name'.split(':').last.to_s.chomp %>")
notify {"${var1}_${var2}": }
}
Running puppet agent gives me this :
Notice: /Stage[main]/Testmodule/Testmodule::Testmod::Bar[abc.com:80]/Notify[abc.com_80]/message: defined 'message' as 'abc.com_80'
Notice: xyz.co.uk_1512
Notice: /Stage[main]/Testmodule/Testmodule::Testmod::Bar[xyz.co.uk:1512]/Notify[xyz.co.uk_1512]/message: defined 'message' as 'xyz.co.uk_1512'

InstantCommons not working in MediaWiki 1.19 and SELinux

I am setting my own MediaWiki website locally, and am not able to get the InstantCommons feature to work (used to directly embed files from commons.wikimedia.org).
I get no error message, the files I try to load from Commons using the following syntax:
[[File:Cervus elaphus Luc Viatour 1.jpg|Cervus elaphus Luc Viatour 1]]
are just not loaded, and I end up with a red link on my page, referring to a non-existing file. It has been 2 days now that I am looking for a solution, but so far without any success.
I am running:
MediaWiki v.1.19.1
Fedora 16 (with SElinux)
PHP 5.3.15
MySQL Ver 14.14 Distrib 5.5.25a, for Linux (x86_64)
I have tried the following two configurations in my LocalSettings.php, without success:
$wgUseInstantCommons = true;
AND
$wgForeignFileRepos[] = array(
'class' => 'ForeignAPIRepo',
'name' => 'shared',
'apibase' => 'http://commons.wikimedia.org/w/api.php',
'fetchDescription' => true, // Optional
'descriptionCacheExpiry' => 43200, // 12 hours, optional (values are seconds)
'apiThumbCacheExpiry' => 43200, // 12 hours, optional, but required for local thumb caching
);
Any suggestion is most welcome.
OK, this is not (yet) an answer, but a debugging suggestion. It looks to me like the HTTP request from your server to Commons is failing for some reason, but unfortunately ForeignAPIRepo doesn't indicate the cause of the error in any way.
This is really a bug in MediaWiki, and should be fixed, but in the mean time, could you please try applying the following diff (or just manually adding the line marked with the + sign) to your includes/filerepo/ForeignAPIRepo.php file:
Index: includes/filerepo/ForeignAPIRepo.php
===================================================================
--- includes/filerepo/ForeignAPIRepo.php (revision 97048)
+++ includes/filerepo/ForeignAPIRepo.php (working copy)
## -385,6 +385,7 ##
if ( $status->isOK() ) {
return $req->getContent();
} else {
+ wfDebug( "ForeignAPIRepo: HTTP GET failed: " . $status->getXML() );
return false;
}
}
After applying it, try loading the file description page for a Commons image and look at the MediaWiki debug log. There should now be a line starting with ForeignAPIRepo: HTTP GET failed: followed by a few lines of XML error dump. That error data should hopefully indicate what's going wrong; please copy and paste it here.
Mine is not a definitive answer either. Referring to Ilmari Karonen's post, I was unable to find or get the getXML() method to execute for my version of Mediawiki v1.23.0. I was looking at the reference documentation found here to try and find any other method calls on the Status class that would give me good troubleshooting info. I ended up finding the following and editing the same file as mentioned in Ilmari Karonen's post includes/filerepo/ForeignAPIRepo.php beginning at line #521:
if ( $status->isOK() ) {
return $req->getContent();
} else {
$error = $status->getErrorsArray();
$dump = print_r($error, true);
wfDebug("ForeignAPIRepo: HTTP GET failed: $dump\n");
return false;
}
The default InstantCommons configuration of older MediaWikis is a bit silly. Due to T114098 I recommend one of the following, which will hopefully fix your problems:
upgrade to MediaWiki 1.27 (when it's released), or
set your LocalSettings.php to hotlink images to save on server-side requests and processing.
$wgUseInstantCommons = false;
$wgForeignFileRepos[] = array(
'class' => 'ForeignAPIRepo',
'name' => 'commonshotlink',
'apibase' => 'https://commons.wikimedia.org/w/api.php',
'hashLevels' => 2,
'url' => 'https://upload.wikimedia.org/wikipedia/commons',
'thumbUrl' => 'https://upload.wikimedia.org/wikipedia/commons/thumb',
'transformVia404' => true,
'fetchDescription' => true,
'descriptionCacheExpiry' => 43200,
'apiThumbCacheExpiry' => 24 * 3600,
);

Resources