I know how i could activate the ttl feature with curl in php, but i wonder if the offical Elasticsearch PHP Library (https://github.com/elasticsearch/elasticsearch-php) does this feature support as well. I've already dig trough the code of the Lib but was not able to figure it out.
Thanks for your help!
I've created my own method to enable ttl feature on a index type. I've also filed an issue on the official Github Repo: https://github.com/elasticsearch/elasticsearch-php/issues/62
class ElasticSearchClient extends \Elasticsearch\Client {
public function enableTtl($params) {
$index = $this->extractArgument($params, 'index');
$type = $this->extractArgument($params, 'type');
$body = json_encode(array($type => array('_ttl' => array('enabled' => true))));
/** #var callback $endpointBuilder */
$endpointBuilder = $this->dicEndpoints;
/** #var \Elasticsearch\Endpoints\Update $endpoint */
$endpoint = $endpointBuilder('Indices\Mapping\Put');
$endpoint->setIndex($index)
->setType($type)
->setBody($body);
$endpoint->setParams($params);
$response = $endpoint->performRequest();
return $response['data'];
}
}
Well, IMHO you need to update the elasticsearch mapping using the putMapping() method. No need for a special method call.
Here is an example that worked in our system.
$params['index'] = 'yourindexname';
$params['type'] = 'yourtypename';
$mapping = [
'_ttl' => [
'enabled' => 'true',
'default' => '14d',
],
'properties' => [
[... add your properties here ...]
]
];
$params['body']['yourtypename'] = $mapping;
$this->getClient()->indices()->putMapping($params);
Related
So I use a Service Class (extends from TYPO3\CMS\Core\Authentication\AuthenticationService) to authenticate our Frontend Users using OAuth2. These Services are automatically instantiated and called via Typos own Middleware: FrontendUserAuthenticator.
In this class I used to save data from the authentication result to $GLOBALS['TSFE']->fe_user using setKey('ses', 'key', 'data'), which seems is not possible anymore since v10. How would I go about still doing this?
The documentation is sparse
https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/9.4/Deprecation-85878-EidUtilityAndVariousTSFEMethods.html
https://docs.typo3.org/m/typo3/reference-coreapi/10.4/en-us/ApiOverview/Context/Index.html
I've tried the following:
constructor injecting the TSFE using DI
class FrontendOAuthService extends AuthenticationService
{
public function __construct(TypoScriptFrontendController $TSFE) {
=> LogicException: TypoScriptFrontendController was tried to be injected before initial creation
changing the Middlewares order to have it instantiate before the Auth Middleware
(packages/extension_name/Configuration/RequestMiddlewares.php)
return [
'frontend' => [
'typo3/cms-frontend/tsfe' => [
'disabled' => true,
],
'vendor/extension_name/frontend-oauth' => [
'target' => \TYPO3\CMS\Frontend\Middleware\TypoScriptFrontendInitialization::class,
'before' => [
'typo3/cms-frontend/authentication',
],
'after' => [
'typo3/cms-frontend/eid',
'typo3/cms-frontend/page-argument-validator',
],
],
],
];
=> UnexpectedValueException: Your dependencies have cycles. That will not work out.
instantiating the TSFE myself
/** #var ObjectManager $objectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** #var DealerService $dealerService */
$lang = $site->getDefaultLanguage();
$siteLanguage = $objectManager->get(SiteLanguage::class, $lang->getLanguageId(), $lang->getLocale(), $lang->getBase(), []);
/** #var TypoScriptFrontendController $TSFE */
$TSFE = $objectManager->get(
TypoScriptFrontendController::class,
GeneralUtility::makeInstance(Context::class),
$site,
$siteLanguage,
GeneralUtility::_GP('no_cache'),
GeneralUtility::_GP('cHash')
);
=> the $TSFE->fe_user is an emptystring ("")
using the UserAspect
/** #var Context $context */
$context = GeneralUtility::makeInstance(Context::class);
$feUser = $context->getAspect('frontend.user');
$feUser->set...
=> Aspects are read-only
adding vars to the user data in the getUser method of the AuthenticationService
(packages/extension_name/Classes/Service/FrontendOAuthService.php)
public function getUser()
{
$user = allBusinessCodeHere();
$user['my_own_key'] = 'myData';
return $user;
=> is not propagated to the UserAspect(frontend.user) nor the $TSFE->fe_user
I'm out of ideas guys.
I had a similar problem when i wanted to use redirects with record links.
I ended up disabling the original redirect middleware and adding my own with a mocked version of tsfe.
The extension can be found here:
https://github.com/BenjaminBeck/bdm_middleware_redirect_with_tsfe
Late to the party, but I had the same issue and was able to solve it:
https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/10.0/Breaking-88540-ChangedRequestWorkflowForFrontendRequests.html states:
Storing session data from a Frontend User Session / Anonymous session
is now triggered within the Frontend User
(frontend-user-authenticator) Middleware, at a later point - once the
page was generated. Up until TYPO3 v9, this was part of the
RequestHandler logic right after content was put together. This was
due to legacy reasons of the previous hook execution order. Migration
Consider using a PSR-15 middleware instead of using a hook, or
explicitly call storeSessionData() within the PHP hook if necessary.
In my MyAuthenticationService extends AbstractAuthenticationService in method getUser() I set $_SESSION['myvendor/myextension/accessToken'] to the token received by the external oauth service. In my SaveSessionMiddleware I save this token to the FrontendUserAuthentication object using setKey() which by then is available:
EXT:myextension/Configuration/RequestMiddlewares.php
return [
'frontend' => [
'myvendor/myextension/save-session-middleware' => [
'target' => \MyVendor\MyExtension\Middleware\SaveSessionMiddleware::class,
'after' => [
'typo3/cms-frontend/authentication',
],
]
]
];
EXT:myextension/Classes/Middleware/SaveSessionMiddleware.php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
class SaveSessionMiddleware implements MiddlewareInterface {
/**
* #param ServerRequestInterface $request
* #param RequestHandlerInterface $handler
* #return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
if (!empty($_SESSION['myvendor/myextension/accessToken'])) {
$this->getFrontendUserAuthentication()->setKey(
'ses',
'myvendor/myextension/accessToken',
$_SESSION['myvendor/myextension/accessToken']);
unset($_SESSION['myvendor/myextension/accessToken']);
}
return $handler->handle($request);
}
private function getFrontendUserAuthentication(): FrontendUserAuthentication {
return $GLOBALS['TSFE']->fe_user;
}
}
I am using Braintree PHP SDK with Laravel framework.
I installed Braintree through composer.
Then, in AppServiceProvider.php, I have added below code in boot():
Braintree_Configuration::environment('sandbox');
Braintree_Configuration::merchantId('merchand_id');
Braintree_Configuration::publicKey('public_key');
Braintree_Configuration::privateKey('private_key');
When trying to generate client_token, I get below error:
Symfony\Component\Debug\Exception\FatalThrowableError: Class
'App\Providers\Braintree_Configuration' not found in
AppServiceProvider.php on line 34
The way you are using braintree seems to follow a deprecated example (my guess previous version of Braintre_php) as Braintree_Configuration class does not exist in the current package.
And you also need to use an "\" before calling the autoloaded class, ex : \Braintree.
This should work in your app/Providers/AppServiceProvider.php file with Braintree 5.x :
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
$gateway = new \Braintree\Gateway([
'environment' => 'sandbox',
'merchantId' => 'use_your_merchant_id',
'publicKey' => 'use_your_public_key',
'privateKey' => 'use_your_private_key'
]);
}
You can have an up to date example here to see some basics sdk function to get started :
https://developers.braintreepayments.com/start/hello-server/php
Please see examples below for braintree/paypal specific examples. This is the most elegant solution that worked for me:
app\Providers\AppServiceProvider.php:
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
// braintree setup
$environment = env('BRAINTREE_ENV');
$braintree = new \Braintree\Gateway([
'environment' => $environment,
'merchantId' => 'merchant_id_example',
'publicKey' => 'public_key_example',
'privateKey' => 'private_key_example'
]);
config(['braintree' => $braintree]);
// braintree setup for specifically for paypal direct integration for those who need it
/*$accessToken = env('PAYPAL_ACCESS_TOKEN');
$braintree = new \Braintree\Gateway([
'accessToken' => $accessToken
]);
config(['braintree' => $braintree]);*/
}
// examplefile.php:
public function token()
{
$braintree = config('braintree');
$clienttoken = $braintree->clientToken()->generate();
}
public function sale()
{
$braintree = config('braintree');
$result = $braintree->transaction()->sale([
'amount' => $amount,
'paymentMethodNonce' => $nonce
]);
}
Did you add a use statement to your AppServiceProvider?
use App\Providers\Braintree_Configuration;
I want to execute ZF3 action with zf-console.
I can do this using zend-mvc-console module and it works fine.
For example.
Application/config/module.config.php:
'console' => [
'router' => [
'routes' => [
'cronroute' => [
'options' => [
'route' => 'sync',
'defaults' => [
'controller' => Controller\ConsoleController::class,
'action' => 'syncEvents'
]
]
]
]
]
],
Application/src/Controller/ConsoleController.php
class ConsoleController extends AbstractActionController
{
/**
* Entity manager.
* #var Doctrine\ORM\EntityManager
*/
private $entityManager;
/**
* User Manager
* #var Application\Service\UserManager
*/
private $userManager;
/**
* Constructor.
*/
public function __construct($entityManager, $userManager)
{
$this->entityManager = $entityManager;
$this->userManager = $userManager;
}
public function syncAction()
{
$response = $this->userManager->syncUserInfo();
return $response ? 'Sync Success' : 'Failed to sync';
}
}
But it says that it will be deprecated:
https://zendframework.github.io/zend-mvc-console/intro/#deprecated
It suggest to use zf-console from zfcampus:
https://github.com/zfcampus/zf-console
But I cannot find a way to execute Controller action or to use my build services (like UserManager).
There is example to build Zend Application and retrieve Service manager:
use Zend\Console\Console;
use Zend\Console\ColorInterface as Color;
use ZF\Console\Application;
use ZF\Console\Dispatcher;
chdir(dirname(__DIR__));
require __DIR__ . '/../vendor/autoload.php'; // Composer autoloader
$application = Zend\Mvc\Application::init(require 'config/application.config.php');
$services = $application->getServiceManager();
$buildModel = $services->get('My\BuildModel');
Is there a way to execute Controller action with it? Or Can I load my UserManager service?
I tried to get My UserManager:
$buildModel = $services->get('Application\Service\UserManager');
But receiving error:
PHP Fatal error: Uncaught exception 'Zend\ServiceManager\Exception\ServiceNotFoundException' with message 'Unable to resolve service "Application\Service\UserManager" to a factory; are you certain you provided it during configuration?' in /var/www/html/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:687
The zend-mvc-console module does seem to be on the edge of deprecation. Just like you I was trying to implement zfcampus/zf-console. Since the mvc-console module seems to be (almost) deprecated, I suggest you use something different than (mvc) controllers for your console work. I used a class that can handle the call (in a way zf-console expects).
This is a dummy example I was working on for my project;
This is script that is called on the command line:
use Zend\Console\Console;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\Glob;
use ZF\Console\Application;
use ZF\Console\Dispatcher;
require_once __DIR__ . '/vendor/autoload.php'; // Composer autoloader
$configuration = [];
foreach (Glob::glob('config/{{*}}{{,*.local}}.php', Glob::GLOB_BRACE) as $file) {
$configuration = ArrayUtils::merge($configuration, include $file);
}
// Prepare the service manager
$smConfig = isset($config['service_manager']) ? $configuration['service_manager'] : [];
$smConfig = new \Zend\Mvc\Service\ServiceManagerConfig($smConfig);
$serviceManager = new ServiceManager();
$smConfig->configureServiceManager($serviceManager);
$serviceManager->setService('ApplicationConfig', $configuration);
// Load modules
$serviceManager->get('ModuleManager')->loadModules();
$routes = [
[
'name' => 'dumb',
'route' => '[--foo=]',
'description' => 'Some really cool feature',
'short_description' => 'Cool feature',
'options_descriptions' => [
'foo' => 'Lorem Ipsum',
],
'defaults' => [
'foo' => 'bar',
],
'handler' => function($route, $console) use ($serviceManager) {
$handler = new \Application\Command\DumbCommand();
return $handler($route, $console);
}
],
];
$config = $serviceManager->get('config');
$application = new Application(
$config['app'],
$config['version'],
$routes,
Console::getInstance(),
new Dispatcher()
);
$exit = $application->run();
exit($exit);
The handler function can use the service manager to inject any dependencies to the command handler:
'handler' => function($route, $console) use ($serviceManager) {
/** #var \Doctrine\ORM\EntityManager $entityManager */
$entityManager = $serviceManager->get(\Doctrine\ORM\EntityManager::class);
/** #var mixed $repository */
$contactRepository = $entityManager->getRepository(\Application\Entity\Contact::class);
$handler = new \Application\Command\DumbCommand($contactRepository);
return $handler($route, $console);
}
The command class is placed in a Command folder, it looks like:
<?php
namespace Application\Command;
use Application\Entity\Contact;
use Application\Repository\ContactRepository;
use Zend\Console\Adapter\AdapterInterface;
use ZF\Console\Route;
class DumbCommand
{
/** #var ContactRepository */
private $contactRepository;
public function __construct($contactRepository)
{
$this->contactRepository = $contactRepository;
}
/**
* #param Route $route
* #param AdapterInterface $console
* #throws \Doctrine\ORM\ORMException
*/
public function __invoke(Route $route, AdapterInterface $console)
{
$console->writeLine('Bob was here');
foreach ($this->contactRepository->findAll() as $item) {
/** #var Contact $item */
$console->writeLine($item->getFirstName() . ' was here');
}
}
}
(
This is my solution:
I addedd console command routes to my module.config.php files
'console' => array(
'commands' => array(
array(
'name' => 'sendemail',
'handler' => PostCommand::class,
),
array(
'name' => 'sendsms',
'handler' => SmsTransferCommand::class,
)
)
),
I created a console.php in /public (this will be run with arguments to start a CLI app)
use Zend\Console\Console;
use Zend\ServiceManager\ServiceManager;
use ZF\Console\Application;
use ZF\Console\Dispatcher;
chdir(dirname(__DIR__));
require_once 'vendor/autoload.php'; // Composer autoloader
// Prepare application and service manager
$appConfig = require 'config/application.config.php';
$application = Zend\Mvc\Application::init($appConfig);
$serviceManager = $application->getServiceManager();
// Load modules
$serviceManager->get('ModuleManager')->loadModules();
$config = $serviceManager->get('config');
$routes = $config['console']['commands']; // This depends on your structure, this is what I created (see. 1.)
$application = new Application(
$config['app'],
$config['version'],
$routes,
Console::getInstance(),
new Dispatcher($serviceManager) // Use service manager as a dependency injection container
);
$exit = $application->run();
exit($exit);
I separated my CLI command handlers into the src/Command folder. My CLI command handlers are services I have defined, created by factories. (This is why I use the service manager as the container - see. 2.)
[serviceEmail here is a local class variable, which is loaded by the factory of this command handler.]
/**
* #param Route $route
* #param AdapterInterface $console
*
* #return int
*/
public function __invoke(Route $route, AdapterInterface $console)
{
$mails = $this->serviceEmail->sendMailFromDb();
$console->writeLine('Sent mails: ' . \count($mails), ColorInterface::WHITE, ColorInterface::RED);
return 0;
}
I created new resources with this code:
class WebserviceRequest extends WebserviceRequestCore {
public static function getResources(){
$resources = parent::getResources();
// if you do not have class for your table
$resources['test'] = array('description' => 'Manage My API', 'specific_management' => true);
$resources['categoryecommerce'] = array('description' => 'o jacie marcin', 'class' => 'CategoryEcommerce');
$mp_resource = Hook::exec('addMobikulResources', array('resources' => $resources), null, true, false);
if (is_array($mp_resource) && count($mp_resource)) {
foreach ($mp_resource as $new_resources) {
if (is_array($new_resources) && count($new_resources)) {
$resources = array_merge($resources, $new_resources);
}
}
}
ksort($resources);
return $resources;
}
}
And new class:
class CategoryEcommerceCore extends ObjectModelCore {
public $category_id;
public $category_core_id;
public static $definition = array(
'table' => "category_ecommerce",
'primary' => 'category_id',
'fields' => array(
'category_core_id' => array('type' => self::TYPE_INT),
)
);
protected $webserviceParameters = array();
}
Webservice is override properly. My class WebserviceRequest is copying to
/override/classes/webservice/WebserviceRequest
but class isn't copying to /override/classes/ when i installing my module.
How to add new resourcess with own logic ? I want to add categories within relation to my table.
Regards
Martin
As soon as there is literally nothing regarding the API except Webkul tutorial... I tried to implement the "Webkul's" tutorial, but also failed. However seems that it's better to use hooks instead of overrides. I used my "reverse engineering skills" to determine the way to create that API, so-o-o-o, BEHOLD! :D
Let's assume you have a custom PrestaShop 1.7 module. Your file is mymodule.php and here are several steps.
This is an install method wich allows you to register the hook within database (you can uninstall and reinstall the module for this method to be executed):
public function install() {
parent::install();
$this->registerHook('addWebserviceResources');
return true;
}
Add the hook listener:
public function hookAddWebserviceResources($resources) {
$added_resources['test'] = [
'description' => 'Test',
'specific_management' => true,
];
return $added_resources;
}
That specific_management option shows you are going to use WebsiteSpecificManagement file instead of database model file.
Create WebsiteSpecificManagement file, called WebsiteSpecificManagementTest (Test - is CamelCased name of your endpoint). You can take the skeleton for this file from /classes/webservice/WebserviceSpecificManagementSearch.php. Remove everything except:
setObjectOutput
setWsObject
getWsObject
getObjectOutput
setUrlSegment
getUrlSegment
getContent (should return $this->output; and nothing more)
manage - you should rewrite it to return/process the data you want.
Add
include_once(_PS_MODULE_DIR_.'YOURMODULENAME/classes/WebserviceSpecificManagementTest.php');
to your module file (haven't figured out how to include automatically).
Go to /Backoffice/index.php?controller=AdminWebservice and setup the new "Auth" key for your application, selecting the test endpoint from the permissions list. Remember the key.
Visit /api/test?ws_key=YOUR_KEY_GENERATED_ON_STEP_4 and see the XML response.
Add &output_format=JSON to your URL to see the response in JSON.
You have to use something like $this->output = json_encode(['blah' => 'world']) within manage method at WebsiteSpecificManagementTest.
I am fiddling with this issue and cannot resolve it - just wanted to check if anyone here can help with tips
I am loading the class and calling the constructor like this
include_once './Myaws.php';
$aws = new Myaws();
$aws->bucket = $images['config']['bucket'];
Myaws.php is as follows
class Myaws {
public $bucket;
function __construct() {
$this->aws = Aws::factory('./config/aws_config.php');
}
}
It works like a charm!
Now the issue
The './config/aws_config.php' is just an array that will change depending on the deployment stage - so I want to make it dynamic. Here is what I do and it doesnt work
include_once './Myaws.php';
$aws = new Myaws();
$aws->bucket = $images['config']['bucket'];
$aws->config = $images['config']['awsconfig'];
And in the Myaws.php, I change the following
class Myaws {
public $bucket;
public $config;
function __construct() {
$this->aws = Aws::factory($this->config);
}
}
It doesn't work :( and neither does the below one
include_once './Myaws.php';
$aws = new Myaws($images['config']['awsconfig']);
$aws->bucket = $images['config']['bucket'];
class Myaws {
public $bucket;
function __construct($config) {
$this->aws = Aws::factory($config);
}
}
This is pretty basic Oops and I don't seem to get it I think. Can anyone suggest me how can I make that variable $config dynamic?
I found the formatting on the included file vs in a passed array to be not 100% compatible. Also check the in the api docs how they use my_profile to pass those credentials.
here is a example of the current method I am using to generation the config
$aws = Aws::factory($this->getAwsConfig());
private function getAwsConfig()
{
return array(
// Bootstrap the configuration file with AWS specific features
'credentials' => array(
'key' => $this->awsKey,
'secret' => $this->awsSecret
),
'includes' => array('_aws'),
'services' => array(
// All AWS clients extend from 'default_settings'. Here we are
// overriding 'default_settings' with our default credentials and
// providing a default region setting.
'default_settings' => array(
'params' => array(
'region' => $this->awsRegion
)
)
)
);
}