How to set langage for translator in controller - web-services

I am trying to make a web service that allows for a system of translation
So I recovered in json
the term to be translated and the language that which I have to translate
My problem is I can not change the defaultLocal in the controller
class TranslateController extends RestController
{
/**
* #param ARDParamFetcher $paramFetcher
* #RequestParam(name="lang", requirements="[a-zA-Z0-9_]+", description="language.")
* #RequestParam(name="msg", requirements="[a-zA-Z0-9_]+", description="message.")
*/
public function translateAction(ARDParamFetcher $paramFetcher)
{
$lang = $paramFetcher->get('lang');
$msg = $paramFetcher->get('msg');
$b = $this->get('translator')->setLocale($lang)->trans($msg);
print_r($b);
exit();
return $this->view(array());
}
}
and here is the content of my file messages.fr.yml
# messages.fr.yml
TXT_1 : il y a %count% objet
Any help please

Make sure you have enabled the translator in config file:
framework:
translator: { fallback: %locale% }
For syntax, see #Roma comment.

I found the solution here is what to write :
$lang = $paramFetcher->get('lang');
$msg = $paramFetcher->get('msg');
$request = $this->getRequest();
$request->setLocale($lang);
$t = $this->get('translator')->trans($msg);

Related

TYPO3 10 : How can I display the metadata categories of the images in my extension?

I created a TYPO3 extension which allows to select several images. I activated metadata via the filemetadata extension. When I browse the image files in a fluid template loop, I try to display the metadata. This works {file.properties.uid}
{file.properties.categories}, but for the categories I get a number. Now I would like to have the category selected.
I used this:
https://coding.musikinsnetz.de/typo3/fluid-viewhelpers/access-system-categories-in-content-elements-templates
<f: if condition = "{files}">
<f: for each = "{files}" as = "file">
<f: for each = "{bg2yg: CategoriesOutput (recUid: data.uid)}" as = "category">
<b style = 'color: blue'> <span class = "{category.title}"> CATEGORY: {category.title} </span> </b> <br />
</ f: for>
</ f: for>
</ f: if>
This displays the main category because 'data.uid': {bg2yg: CategoriesOutput (recUid: data.uid)}
However, I want the categories of images, I tested this:
<f: for each = "{bg2yg: CategoriesOutput (recUid: file.properties.uid)}" as = "category">
Without success ! Do you have an idea ?
Best regards,
Bruno
thank you for your respective help. Here I coded this:
<?php
/**
* This file is part of the "hexagonalgallery" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BG2YG\Hexagonalgallery\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
* will return certain system categories (sys_category) data of an element
* either as an array or as a string with certain parameters
*
* EXAMPLES:
*
* EMBEDDING IN TEMPLATE: {namespace my = YourVendor\YourExtension\ViewHelpers}
*
* call an array with all category data to be used in a loop, e.g. for an HTML tag for each files:
* <f:if condition="{file}">
* <f:for each="{my:FileCategoriesOutput(recUid: data.uid)}" as="category">
* <span class="{category.title}">{category.title}</span>
* </f:for>
* </f:if>
*
* call a “data-categories” attribute with the slug field of the categories, comma-separated (default):
* {my:FileCategoriesOutput(recUid: file.properties.uid, tableName: 'sys_file_metadata', fieldString: 'title', htmlAttr: 'data-categories')}
* output: ' data-categories="catx,caty"'
*
* call all categories as CSS classes (space as string separator, prefix 'cat-' for each files)
* {my:FileCategoriesOutput(recUid: file.properties.uid, tableName: 'sys_file_metadata', fieldString: 'title', stringSeparator: ' ', catPrefix: 'cat-')}
* output: 'cat-catx cat-caty'
*/
class FileCategoriesOutputViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
public function initializeArguments()
{
$this->registerArgument('recUid', 'integer', 'record UID, e.g. of a content element', true);
$this->registerArgument('tableName', 'string', 'optional: table of records you want the categories returned for (default: tt_content)', false, 'tt_content');
$this->registerArgument('fieldString', 'string', 'optional: name of sys_categories table field – if given, the return value will be a string', false, null);
$this->registerArgument('stringSeparator', 'string', 'optional: separator for string', false, ',');
$this->registerArgument('htmlAttr', 'string', 'optional: wrap in attribute for HTML tag (in case of fieldString given)', false, null);
$this->registerArgument('catPrefix', 'string', 'optional: prefix for each category (e.g. for CSS classes)', false, null);
}
/**
* #return mixed
*/
public function render()
{
$recUid = $this->arguments['recUid'];
$tableName = $this->arguments['tableName'];
$fieldString = $this->arguments['fieldString'];
$stringSeparator = $this->arguments['stringSeparator'];
$htmlAttr = $this->arguments['htmlAttr'];
$catPrefix = $this->arguments['catPrefix'];
define(DEBUG,false);
/*
SELECT uid_local FROM sys_file_reference WHERE uid = 152
*/
if (DEBUG)
echo "<b style='color:blue;'>\$recUid=".$recUid."</b><br />";
/**
* default query for sys_file_reference table
* SQL : SELECT uid_local FROM sys_file_reference WHERE uid = $recUid
*/
$queryBuilder0 = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
$queryBuilder0->select('uid_local');
$queryBuilder0->from('sys_file_reference');
$queryBuilder0->where(
$queryBuilder0->expr()->eq('sys_file_reference.uid', $queryBuilder0->createNamedParameter($recUid, \PDO::PARAM_INT)));
$result_uid = $queryBuilder0->execute();
$uid=$result_uid->fetch();
$uid=$uid['uid_local'];
if (DEBUG)
echo "<b style='color:blue;'>\$uid=".print_r($uid)."</b><br />";
/**
* default query for sys_category table
*/
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_category');
/**
* select the fields that will be returned, use asterisk for all
*/
$queryBuilder->select('sys_category.uid', 'sys_category.title', 'sys_category_record_mm.uid_foreign', 'sys_category_record_mm.tablenames');
$queryBuilder->from('sys_category');
$queryBuilder->join(
'sys_category',
'sys_category_record_mm',
'sys_category_record_mm',
$queryBuilder->expr()->eq('sys_category_record_mm.uid_local', $queryBuilder->quoteIdentifier('sys_category.uid'))
);
$queryBuilder->where(
$queryBuilder->expr()->eq('sys_category_record_mm.uid_foreign', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
$queryBuilder->expr()->like('sys_category_record_mm.tablenames', $queryBuilder->createNamedParameter($tableName))
);
$result = $queryBuilder->execute();
$res = [];
$returnString = '';
$i = 1;
while ($row = $result->fetch()) {
$res[] = $row;
if ($fieldString !== null) {
if (isset($row[$fieldString])) {
$returnString .= ($i === 1) ? '' : $stringSeparator;
$returnString .= ($catPrefix !== null) ? $catPrefix : '';
$returnString .= $row[$fieldString];
}
}
$i++;
}
if (DEBUG) {
echo "\$returnString=" . $returnString . "<br />";
echo "\$res=<b style='color:red;'>" . print_r($res) . "</b><br />";
}
if ($returnString !== '') {
return ($htmlAttr !== null)
? ' ' . $htmlAttr . '="' . $returnString . '"'
: $returnString;
} elseif ($fieldString !== null) {
return '';
} else {
return $res;
}
}
}
And it works. Thank you for indicating to me if this code seems to you written in the rules of art.
Best regards,
Bruno
It looks like categories are not handled in the model, so the fastest thing you can do is to create your own ViewHelper for fetching them as suggested in answer to a similar question, my fast test for TYPO3 9.5
IMPORTANT! for ver.: 10+ check annotation changes at the bottom of this post.
<?php
namespace VENDOR\Toolbox\ViewHelpers;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
*
* #package TYPO3
* #subpackage toolbox
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 2 or later
* #author Marcus Biesioroff biesior#gmail.com>
*
* Sample ViewHelper for listing file's categories
*
* Usage:
* {namespace toolbox=VENDOR\Toolbox\ViewHelpers}
* or in ext_tables.php:
* $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['toolbox'] = ['VENDOR\Toolbox\ViewHelpers'];
*
* <toolbox:fileCategories file="{file}" />
* or
* {toolbox:fileCategories(file: file)}
*/
class FileCategoriesViewHelper extends AbstractViewHelper
{
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository
* #inject
*/
protected $categoryRepository;
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('file', 'mixed', 'File');
}
public function render()
{
/** #var FileReference $fileRef */
$fileRef = $this->arguments['file'];
$file = $fileRef->getOriginalFile();
$uid = $file->getUid();
/** #var QueryResult $res */
$res = $this->getCategories($uid);
return $res->toArray();
}
private function getCategories($uid)
{
$query = $this->categoryRepository->createQuery();
$sql = "SELECT sys_category.* FROM sys_category
INNER JOIN sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid AND sys_category_record_mm.fieldname = 'categories' AND sys_category_record_mm.tablenames = 'sys_file_metadata'
INNER JOIN sys_file_metadata ON sys_category_record_mm.uid_foreign = sys_file_metadata.uid
WHERE sys_file_metadata.file = '" . (int)$uid . "'
AND sys_category.deleted = 0
ORDER BY sys_category_record_mm.sorting_foreign ASC";
return $query->statement($sql)->execute();
}
}
So you can use it within your Fluid template like:
<h3>File categories:</h3>
<ul>
<f:for each="{toolbox:fileCategories(file: file)}" as="file_cat">
<li>{file_cat.title}</li>
</f:for>
</ul>
Don't forget to use your own vendor and subpackage key.
Of course, after injecting anything don't forget to flush your caches, sometimes maaaany times.
Important info for ver.: 10.* +
According to this article #inject annotation is depreciated in ver. 9.x and removed in ver." 10.x You should use #TYPO3\CMS\Extbase\Annotation\Inject instead.
So proper injection of the categoryRepository in TYPO3 10.x and newer should look like:
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository
* #TYPO3\CMS\Extbase\Annotation\Inject
*/
protected $categoryRepository;
You can also search for deprecated annotations within your ext via Upgrade module > Scan Extension Files

Laravel 5.5 Service Provider

I am trying to have a custom service provider with common methods that I am using throughout my application. However I am getting an error target not instantiable. I have the same working fine in Laravel 5.3 but now its not working in Laravel 5.5. Here is my code:
In the app\Helpers folder, I have created a folder Contracts with an interface FrontendContracts.
namespace App\Helpers\Contracts;
Interface FrontendContracts{
public function randomString($len);
}
In app\Helpers I have a class FrontendMethods which implements the interface
namespace App\Helpers;
use App\Helpers\Contracts\FrontendContracts;
class FrontendMethods implements FrontendContracts{
public function randomString($len){
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmonpqrstuvwxyz";
$result = "";
$charArray = str_split($chars);
for($i = 0; $i < $len; $i++){
$randItem = array_rand($charArray);
$result .= "".$charArray[$randItem];
}
$result .= time();
return $result;
}
}
In the app\Providers I have FrontendServiceProvider class with:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Helpers\FrontendMethods;
class FrontendServiceProvider extends ServiceProvider{
protected $defer = true;
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot(){
//
}
/**
* Register the application services.
*
* #return void
*/
public function register(){
$this->app->bind('App\Helpers\Contracts\FrontendContracts', function(){
return new FrontendMethods();
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides(){
return ['App\Helpers\Contracts\FrontendContracts'];
}
}
I have registered the provider in the providers array as:
App\Providers\FrontendServiceProvider::class,
I am getting the error message Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}
and Target [App\Helpers\Contracts\FrontendContracts] is not instantiable.
Can someone kindly point at to me what I am doing wrong?
I don't think you need the provides() method in your FrontendServiceProvider class. Try removing this.

PHPunit: testing a Repository

I am testing my repository in Laravel and I came across a few issues, most probably with regards to the structure of my methods.
So, my repository looks like:
<?php
namespace Repositories\User;
use App\Test\Models\Entities\User;
use Illuminate\Database\Eloquent\Model;
class UserRepository implements UserInterface
{
/**
* #var Model $userModel
*/
protected $userModel;
/**
* Setting our class $userModel to the injected model
*
* #param Model $userModel
* #return UserRepository
*/
public function __construct(Model $userModel)
{
$this->userModel = $userModel;
}
/**
* Returns the User object associated with the userEmail
*
* #param string $userEmail
* #return User | null
*/
public function getUserByEmail($userEmail)
{
// Search by email
$user = $this->userModel
->where('email', '=', strtolower($userEmail))
->first();
if ($user) {
return $user->first();
}
return null;
}
}
/**
* #param $id
* #param $email
* #param $source
*
* #dataProvider usersDataProvider
*/
public function testGetUserByEmail($id, $email, $source)
{
$user = new User();
$user->id = $id;
$user->email = $email;
$user->user_source_id = $source;
$this->user->shouldReceive('getUserByEmail')->once()
->andReturn($user);
}
I am quite new working with Mockery and am just wondering whether I am following the correct approach in order to test my getUserByEmail($email) method. Please bare in mind that (as expected) getUserByEmail($email) makes a call to the Database.
Also, this is the message that I receive:
PHP Fatal error: Call to a member function connection() on null in /private/var/www/ff-php-prelaunch/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php, which probably implies that there is no initialized connection to the DB.
UPDATE
Btw, my setUp() is as follows:
public function setUp()
{
$this->user = Mockery::mock('App\Test\Models\Entities\User');
parent::setUp();
}
You probably don't extend the default TestCase class provided by Laravel in the tests directory. Your environment is not correct and you have no connection to the database.
If you don't want to actually query the database you should use Mockery to create a mock of your dependencies (here $userModel). You basically create a Mock the following way, I didn't test this code but the general idea is here.
protected function setUp() {
parent::setUp();
$userModelMockedMethods = [
'where' => 'some return'
];
// This is our dependency mock
$userModelMock = Mockery::mock(Model::class, $userModelMockedMethods);
// this mock now will return 'some return' if you call the `where` method
// on it. If you wish the where method to return something callable, you
// should return another mock instead of a string
// This replaces the mock in the dependency manager.
$this->app->instance(Model::class, $UserModelMock);
}

phpunit mock web service(not WSDL)

I have a small problem which I think is quite simple to solve for experienced PHPUnit users.
I'm working with ZF2.
I'm working with a web service that returns plain text(CSV). I'd like to unit test the service that I've created.
I currently have a working configuration which is not the right way to do it I think.. I'm using mocks now when I'm unit testing my models and I have seen that PHPUnit has a special mock for web services, but that only supports WSDL.
Beneath you'll find my code and I hope someone can help me out with some explanation about the best practice for this situation.
The docs and the topics out here did not help me out (yet).
Thanks in advance!
The test itself:
public function testCanSearchSteeringWheels()
{
// Create the entry and fill it with the data that should be retrieved from the web service
$steeringWheelEntity = new SteeringWheelEntity();
$steeringWheelEntity->setId('170633')
->setName('Nice steering wheel one')
->setGrossPrice(100)
->setNetPrice(75);
// Setup the http client which whill make the final call to the web service
$httpClient = new Client();
$httpClient->setOptions(array(
'maxredirects' => 5,
'timeout' => 60,
))
->setAuth($this->config['supplier_name']['api']['username'], $this->config['supplier_name']['api']['password'])
;
$steeringWheelService = new SteeringWheelService($httpClient, new Request(), $this->config['supplier_name']);
// Search for a steering wheel by id code
$searchResult = $steeringWheelService->search('ID=5221552658987');
$this->assertEquals($steeringWheelEntity, $searchResult[0]);
}
The SteeringWheelEntity
namespace SupplierName\Entity;
class SteeringWheelEntity
{
// vars
// exchange array method
// getters methods
// setters methods
}
The SteeringWheelService
namespace SupplierName\Service;
use SupplierName\Entity\SteeringWheelEntity;
class SteeringWheelService extends AbstractWebService
{
/**
* search()
*
* #param string $param
* #return array
*/
public function search($param)
{
$this->appendUrl('ww0800?3,' . $param);
$response = $this->dispatch();
$parsedBody = $this->parse($response->getBody());
$entities = array();
foreach ($parsedBody as $data)
{
$steeringWheel = new SteeringWheelEntity();
// Fill SteeringWheelEntity with data
$entities[] = $steeringWheel;
}
return $entities;
}
}
The AbstractWebService
use \Zend\Http\Client;
use \Zend\Http\Request;
class AbstractWebService
{
private $httpClient;
private $request;
private $response;
protected $config;
private $url;
public function __construct(Client $httpClient, Request $request, Array $config)
{
$this->url = $config['api']['url'];
$this->httpClient = $httpClient;
$this->request = $request;
$this->config = $config;
}
protected function setUrl($url)
{
$this->url = $url;
return $this->url;
}
protected function appendUrl($string)
{
$this->url .= $string;
}
protected function getUrl()
{
return $this->url;
}
public function dispatch()
{
$this->request->setUri($this->getUrl());
$this->response = $this->httpClient->dispatch($this->request);
if (!$this->response->isSuccess()) {
throw new \Exception('HTTP error #' . $this->response->getStatusCode() . ' when connecting to ' . $this->getUrl() . '.');
}
return $this->response;
}
public function parse()
{
// Parse the content
}
}
Rather than using a mock for a web service. Could you just mock the \Zend\Http\Request and \Zend\Http\Client objects as they are doing the work for you? This way you have control over what the Zend objects return to you versus having to try to mock the web service.
That would be how I would go about testing the services.

Testing Unit of DependencyInjection

I'm using this example here to do my test unit of DependencyInjection, but, when I'm testing, I get the following error :
Myapp\MyBundle\Tests\DependencyInjection\MybundleExtensionTest::test Load
Argument 1 passed to Myapp\MyBundle\DependencyInjection\Configuration::buil
dPathNode() must be an instance of Myapp\MyBundle\DependencyInjection\NodeD
efinition, instance of Symfony\Component\Config\Definition\Builder\ArrayNodeDefi
nition given, called in E:\wamp\www\testingUnit\src\Myapp\MyBundle\Dependen
cyInjection\Configuration.php on line 33 and defined
DependencyInjection/MyappMybundleExtensions.php
<?php
namespace Myapp\Mybundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Config\Definition\Processor;
class MybundleExtension extends Extension
{
/**
* Build the extension services
*
* #param array $configs
* #param ContainerBuilder $container
*/
public function load(array $configs, ContainerBuilder $container)
{
$processor = new Processor();
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('file.yml');
$config = $processor->processConfiguration($configuration, $configs);
$container->setParameter('FashionWeb\ProductBundle\Controller\FamilyController::showFamilyAction', $config['action']);
}
}
Tests/DependencyInjection/MyappMyBundleExtensionsTest.php
namespace Myapp\Mybundle\Tests\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class Myapp\MybundleExtensionTest extends \PHPUnit_Framework_TestCase
{
public function testLoad()
{
$container = new ContainerBuilder();
$extension = new MyappMybundleExtension();
$extension->load(array(), $container);
$this->assertEquals('FashionWeb\ProductBundle\Controller\FamilyController::showFamilyAction', $container->getParameter('myapp_mybundle.action'), sprintf('%s parameter is correct', 'myapp_mybundle.action'));
}
}
Do you have use Symfony\Component\Config\Definition\Builder\NodeDefinition; in your Configuration.php file ?
Error seems to be caused by missing use statement.