Soap and laravel don't work together - php

I'm trying to connect my client soap to my serve soap without sucess on Laravel. My SO is ubuntu 16.
I've searched on google and here on stackoverflow and I didn't find anything.
This is my route:
Route::get('/server.wsdl','SOAP\WsdlController#index');
Route::any('/server','SOAP\ServidorController#server');
Route::get('/client','SOAP\ClientController#client');
This is my ClientController:
use Zend\Soap\Client;
public function client(){
$client = new Client('http://localhost:8080/server.wsdl',[
'soap_version'=> SOAP_1_1
]);
$array = array(
"num1" => 10,
"num2" => 10
);
print_r($client->sum($array));
}
This is my ServidorController:
use Zend\Soap\Server;
class ServidorController extends Controller
{
public $serverUrl = "http://localhost:8080/server";
public function server()
{
$soap = new Server($this->serverUrl . '.wsdl');
$soap->setClass('App\Http\Controllers\Classes\Hello');
$soap->handle();
}
}
This is my WsdlController:
use Zend\Soap\AutoDiscover;
class WsdlController extends Controller
{
public $serverUrl = "http://localhost:8080/server";
public function index()
{
$soapAutoDiscover = new AutoDiscover(new
\Zend\Soap\Wsdl\ComplexTypeStrategy\ArrayOfTypeSequence());
$soapAutoDiscover->setBindingStyle(array('style' => 'document'));
$soapAutoDiscover->setOperationBodyStyle(array('use' =>
'literal'));
$soapAutoDiscover->setClass('App\Http\Controllers\Classes\Hello');
$soapAutoDiscover->setUri($this->serverUrl);
$soapAutoDiscover->handle();
}
}
Finally this is my class Hello:
class Hello
{
/**
* #param int $num1
* #param int $num2
* #return int
*/
function soma($num1, $num2)
{
return $num1 + $num2;
}
}
My framework shows this error:
SoapFault
Too few arguments to function App\Http\Controllers\Classes\Hello::soma(), 1 passed and exactly 2 expected
But in the function's declaration I putted the 2 arguments. What's happened whith this?

Ah, I take it soma is actually sum, and you translated before posting?
Look here:
$client->sum($array);
You pass one argument, an array, whereas your class expects two arguments.
Instead:
$client->sum($array['num1'], $array['num2']);

This were my errors: I was running the command on terminal 1 "php artisan serve" and in the terminal 2, I was running "php artisan serve --port:8080" and as you can see bellow, the $client was pointing to 'http://localhost:8080/server.wsdl'.
$client = new Client('http://localhost:8080/server.wsdl',[
'soap_version'=> SOAP_1_1
]);
I've solved my ask when I installed, start and setting the apache2 server on ubuntu 16. I've pointed the default folder to my laravel aplication and it works fine.

Related

Code coverage from a php built in server is not correct

Objective
I am writing phpunits tests, and I want to get the code coverage.
Problem
To do End To End tests, I have a Php build in server to setup my API, then the tests call this api.
But everything that is being executed by the server is not in the report.
For exemple I tested a controller with api calls, and on my report there is 0%.
All the file that are tested without the Php build int server are ok, it's only the tests that works with that are not counted.
Is there a way to count it ?
Some code
I am using a php that create an http server to do end to end tests on my api.
Here is my class
<?php
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Process\Process;
class ApiTestCase extends \PHPUnit\Framework\TestCase
{
protected static string $public_directory;
protected static Process $process;
const ENVIRONMENT = 'test';
const HOST = '0.0.0.0';
const PORT = 9876; // Adjust this to a port you're sure is free
public static function setUpBeforeClass(): void
{
$command = [
'php',
'-d',
'variables_order=EGPCS',
'-S',
self::HOST . ':' . self::PORT,
'-t',
self::$public_directory,
self::$public_directory.'/index.php'
];
// Using Symfony/Process to get a handler for starting a new process
self::$process = new Process($command, null, [
'APP_ENV' => self::ENVIRONMENT
]);
// Disabling the output, otherwise the process might hang after too much output
self::$process->disableOutput();
// Actually execute the command and start the process
self::$process->start();
// Let's give the server some leeway to fully start
usleep(100000);
}
public static function tearDownAfterClass(): void
{
self::$process->stop();
}
/**
* #param array<string,mixed>|null $data
* #param string $path
* #param string $method
* #return ResponseInterface
* #throws \GuzzleHttp\Exception\GuzzleException
*/
protected function dispatch(string $path, string $method = 'POST', ?array $data = null): ResponseInterface
{
$params = [];
if ($data) {
$params['form_params'] = $data;
}
$client = new Client(['base_uri' => 'http://127.0.0.1:' . self::PORT]);
return $client->request($method, $path, $params);
}
}
So in my test i can use it like that and it works fine
class MyApiTest extends \App\Tests\ApiDbTestCase
{
public function testAuthClientSuccess()
{
// creation of $parameters
$res = $this->dispatch('/v1/user/my/url', 'POST', $parameters);
// My asserts are done after that
}
}
I am using github action to create
name: Phpunit coverage
on: [push]
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: php-actions/composer#v6
- uses: php-actions/phpunit#v3
with:
php_extensions: pdo_pgsql xdebug
args: --coverage-html
env:
XDEBUG_MODE: coverage
- name: Archive code coverage results
uses: actions/upload-artifact#v2
with:
name: code-coverage-report
path: output/code-coverage

Factory relationship returning null laravel testing

I'm trying to unit testing a service that handles the registration of a user in Laravel.
This is the service:
public function completeRegistration(Collection $data)
{
$code = $data->get('code');
$registerToken = $this->fetchRegisterToken($code);
DB::beginTransaction();
$registerToken->update(['used_at' => Carbon::now()]);
$user = $this->userRepository->update($data, $registerToken->user);
$token = $user->createToken(self::DEFAULT_TOKEN_NAME);
DB::commit();
return [
'user' => $user,
'token' => $token->plainTextToken,
];
}
Where the update method has the following signature:
<?php
namespace App\Repositories\User;
use App\Models\User;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
interface UserRepositoryInterface
{
public function create(Collection $data): User;
public function update(Collection $data, User $user): User;
}
With my test being:
/**
* Test a user can register
*
* #return void
*/
public function test_user_can_complete_registration()
{
$userRepositoryMock = Mockery::mock(UserRepositoryInterface::class);
$registerTokenRepositoryMock = Mockery::mock(RegisterTokenRepository::class);
$userFactory = User::factory()->make();
$registerTokenFactory = RegisterToken::factory()
->for($userFactory)
->timestamped()
->make(['user_id' => $userFactory->id]);
dd($registerTokenFactory->user);
$userRepositoryMock
->expects($this->any())
->once()
->andReturn($userFactory);
....
}
When I run phpunit --filter=test_user_can_complete_registration I get the following error:
1) Tests\Unit\Services\Auth\AuthServiceTest::test_user_can_complete_registration
TypeError: Argument 2 passed to Mockery_0_App_Repositories_User_UserRepositoryInterface::update() must be an instance of App\Models\User, null given, called in /var/www/app/Services/Auth/AuthService.php on line 64
/var/www/app/Services/Auth/AuthService.php:64
/var/www/tests/Unit/Services/Auth/AuthServiceTest.php:88
This tells me that the user relationship on $registerTokenFactory is null. When I do:
public function test_user_can_complete_registration()
{
...
dd($registerTokenFactory->user);
}
I get the output null. I'm trying to test the service without hitting the database. How can I attach the user relationship to the $registerTokenFactory object? I have tried using for and trying to attach directly:
$registerTokenFactory = RegisterToken::factory()
->for($userFactory)
->timestamped()
->make(['user_id' => $userFactory->id, 'user' => $userFactory]);
In Laravel factories make() does only create the model and does not save it. For relationship to work, you will need your models to be saved.
$userFactory = User::factory()->create();
Since you do not want to use a Database, which is wrong in my opinion. People don't like writing tests, so when we have to do it make it simple, mocking everything to avoid databases is a pain. Instead an alternative is to you Sqlite to run in memory, fast and easy. A drawback is some functionality does not work there JSON fields and the version that are in most Ubuntu distributions does not respect foreign keys.
If you want to follow the path you are already on, assigned the user on the object would work, you have some left out bits of the code i assume.
$userRepositoryMock = Mockery::mock(UserRepositoryInterface::class);
$registerTokenRepositoryMock = Mockery::mock(RegisterTokenRepository::class);
$user = User::factory()->make();
$registerToken = RegisterToken::factory()
->for($userFactory)
->timestamped()
->make(['user_id' => $user->id]);
$registerToken->user = $user;
$registerTokenRepositoryMock
->expects('fetchRegisterToken')
->once()
->andReturn($registerToken);
$userRepositoryMock
->expects($this->any())
->once()
->andReturn($user);
// execute the call

Call a Controller method from a Command in Laravel

I have a Command that is listening via Redis Pub/Sub. When a Publish is received, I want to call a controller method so that I can update the database.
However, I have not been able to find any solution on how to call a controller method with parameters from inside of the project but outside of the routes. The closest thing I have seen is something like:
return redirect()->action(
'TransactionController#assignUser', [
'transId' => $trans_id,
'userId' => $user_id
]);
My complete command that I've tried looks like this:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
class RedisSubscribe extends Command
{
protected $signature = 'redis:subscribe';
protected $description = 'Subscribe to a Redis channel';
public function handle()
{
Redis::subscribe('accepted-requests', function ($request) {
$trans_array = json_decode($request);
$trans_id = $trans_array->trans_id;
$user_id = $trans_array->user_id;
$this->assignUser($trans_id, $user_id);
});
}
public function assignUser($trans_id, $user_id)
{
return redirect()->action(
'TransactionController#assignUser', [
'transId' => $trans_id,
'userId' => $user_id
]);
}
}
However, this does not seem to work. When I run this Command, I get an error that assignUser() cannot be found (even though it exists and is expecting two paramters). I am also not sure a "redirect" is really what I am after here.
Is there some other way to call a controller function in a Command, or some other way that would make this possible to do?
If your controller does not have any required parameters, you can just create the controller as a new object, and call the function.
$controller = new TransactionController();
$controller->assignUser([
'transId' => $trans_id,
'userId' => $user_id
]);

How to clear cache in Controller in Symfony3.4?

after migration Symfony from 3.3 to 3.4, my function not working (it works before). I have to clear cache in controller, and when I execute command below, function returns error.
exec(sprintf(
"php %s/bin/console cache:clear --env=prod",
$this->getParameter('kernel.project_dir')
));
It returns something like that:
Fatal error: require(): Failed opening required '/[...]/var/cache/prod/ContainerAcrshql/getTwig_ExceptionListenerService.php' (include_path='.:/usr/local/share/pear') in /[...]/var/cache/prod/ContainerAcrshql/appProdProjectContainer.php on line 764 Fatal error: require(): Failed opening required '/[...]/var/cache/prod/ContainerAcrshql/getSwiftmailer_EmailSender_ListenerService.php' (include_path='.:/usr/local/share/pear') in /[...]/var/cache/prod/ContainerAcrshql/appProdProjectContainer.php on line 764
In addition I can tell You, that in dev environment it works properly. Also when project run localy and simulate prod env (in address bar I type app.php after localhost:8000). I haven't other server to check if problem still occured
I'm calling an already implemented Symfony's command that clear or warmup cache (tested on Symfony 4).
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
class CommandController extends AbstractController
{
/**
*
* #Route("/command/cache/clear", name="command_cache_clear")
*/
public function command_cache_clear(KernelInterface $kernel)
{
return $this->do_command($kernel, 'cache:clear');
}
/**
*
* #Route("/command/cache/warmup", name="command_cache_warmup")
*/
public function command_cache_warmup(KernelInterface $kernel)
{
return $this->do_command($kernel, 'cache:warmup');
}
private function do_command($kernel, $command)
{
$env = $kernel->getEnvironment();
$application = new Application($kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => $command,
'--env' => $env
));
$output = new BufferedOutput();
$application->run($input, $output);
$content = $output->fetch();
return new Response($content);
}
}
You should add a valid permissions to the var/ directory to access to cache files:
chmod ... var/ -R
The user used when accessing from web is www-data

cakephp-sms not working transport class not found

I am trying to send sms using cakephp-sms plugin
The documentation is quite clear and brief. I installed it using Composer in my app/Plugin directory. I also installed xi-sms using composer. This was installed in the Vendor directory. In my controller for sending sms. I included App::uses('CakeSms', 'Sms.Network/Sms') and implemented an InfobipSmsTransport class in the Sms/Lib/Network/Sms. Below is my class
<?php
use Xi\Sms\Gateway\InfobipGateway;
App::uses('AbstractSmsTransport', 'Sms.Network/Sms');
class InfobipSmsTransport extends AbstractSmsTransport {
const INFOBIP_USER = 'XXXXX';
const INFOBIP_PASSWORD = 'XXXXXXX';
/**
*
* #param CakeSms $sms
* #return bool Success
*/
public function send(CakeSms $sms) {
$gw = new InfobipGateway(
self::INFOBIP_USER,
self::INFOBIP_PASSWORD
);
$service = new Xi\Sms\SmsService($gw);
$msg = new Xi\Sms\SmsMessage(
$sms->message(),
$sms->from(),
$sms->to()
);
$response = $service->send($msg);
return !empty($response);
}
}
?>
When I try to send an SMS however I get the following error
Class "InfobipSmsTransport" not found.. I have no idea what am doing wrong? Any clues or suggestions are welcome.
The CakeSms class was not loading the plugin. This is the line of code where it was failing.
App::uses($transportClassname, $plugin . 'Network/Sms');.
In my app/Config/sms.php I just changed this 'transport' =>'Infobip' to
'transport' =>'Sms.Infobip'. The plugin is now being loaded properly and the class is found.

Categories