I read, i try, i looking informations about how add / update combinations by webservice, in presta 1.5.3 but still i don't know how to do that.
Can someone help me?
Assigning combinations to products via Webservice is a multi-step operation (unlike CSV import).
given a product with id_product
add product_options (BO Attribute Names)
add product_option_values (BO Attribute Values) to product_options
add combinations while specifying id_product
Start by initialising PrestaShopWebservice with DEBUG=true:
$api = new PrestaShopWebservice($psShopUrl, $psAuthKey, $psDebug);
Instead of building the XML from scratch get a template for the resource you need like this:
$sxml = $api->get(array('url' => $psShopUrl.'api/'.$resource.'?schema=blank'));
The response is a SimpleXMLElement which is a easier to manipulate than DOM.
NB: The response contains all wrapper nodes and you must send the same back in your request i.e. PSWebServiceLibrary will not recreate them for you.
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<combination>
...
</combination>
</prestashop>
SXML manipulation example:
$schema = $api->get(array('url' => $psShopUrl.'api/product_options?schema=blank'));
$data = $schema->children()->children();
$data->is_color_group = false;
$data->group_type = $group_type; // radio, select
$data->name->language[0] = 'attribute private name';
$data->public_name->language[0] = 'attribute public name';
$xml = $schema->asXML(); // all of it!
$ret = $api->add(array('resource' => 'product_options', 'postXml' => $xml));
$id_attribute_group = (int)$ret->children()->children()->id; // save for next step
Then get product_option_values schema, set data and the id_attribute_group from previous step. And so on.
Updating is the same except you will get the resource by id and then edit:
$sxml = $api->get(array('resource' => $resource, 'id' => $id));
...
$ret = $api->edit(array('resource' => $resource, 'id' => $id, 'putXml' => $xml));
As for adding multiple id values to the product_option_values node in the combinations resource you can use the array_push shortcut []:
$data->associations->product_option_values->product_option_values[]->id = 123;
$data->associations->product_option_values->product_option_values[]->id = 456;
This is work fine for me :
$webService = new PrestaShopWebservice($url, $api_key, FALSE);
$xml = $webService->get(array('url' => $url .'/api/combinations?schema=blank'));
$resources = $xml->children()->children();
$resources->id_product = $ps_product_id;
$resources->wholesale_price = $wholesale_price;
$resources->price = $price;
$resources->unit_price_impact = $unit_price_impact;
$resources->minimal_quantity = $minimal_quantity;
$resources->quantity = $quantity;
$resources->weight = $weight;
$resources->associations->product_option_values->product_option_value[0]->id = $color_id;
$resources->associations->product_option_values->product_option_value[1]->id = $size_id;
$request = $xml->asXML();
//This is a function that curl request to specific URL using method (POST)
$response = ps_curl($url . '/api/combinations', $request, 'POST', $api_key);
$xml_load = simplexml_load_string($response);
$id = $xml_load->combination->id;
I hope that's helpful :)
Related
I am trying to test a Service which preprocessed a form and finally saves it. Within the creating of that form:
$this->container->get('security.token_storage')->getToken()->getUser();
is called to get currently logged in user as a default value for a field.
Right now I am having this (extending Symfony\Bundle\FrameworkBundle\Test\WebTestCase):
private $pages;
private $formFactory;
protected function setUp()
{
self::bootKernel();
$client = self::$kernel->getContainer()->get('test.client');
$client->setServerParameters([
'HTTP_HOST' => 'ajax.localhost.dev:10190',
'CONTENT_TYPE' => 'application/json',
'HTTP_X-Requested-With' => 'XMLHttpRequest',
'HTTP_USER_AGENT' => 'Symfony/2.0',
'PHP_AUTH_USER' => 'root',
'PHP_AUTH_PW' => 'root#localhost.dev'
]);
$this->pages = self::$kernel->getContainer()->get('app.pages');
$this->formFactory = self::$kernel->getContainer()->get('form.factory');
}
public function testNewPage() {
$page = new Page();
//shortened
$form = $this->formFactory->create(PageType::class, $page);
}
But that gives me the error:
Call to a member function getUser() on null
What shows that there is no security token.
How can I come over that?
UPDATE
Thanks to the comments of #LBA I tried that code, with no luck:
$session = self::$kernel->getContainer()->get('session');
$token = new UsernamePasswordToken('root', 'root', 'main', ['ROLE_USER', 'ROLE_ROOT']);
$session->set('_security_main', serialize($token));
$session->save();
The part with setting a Cookie as described here is missing, since the $kernel has no method getCookieJar()
I could finally make it work like so:
protected function setUp()
{
self::bootKernel();
$root = new User();
$root->setUsername('root');
$root->setPassword('root');
$root->setEmail('root#localhost.dev');
$token = new UsernamePasswordToken($root, null, 'main', ['ROLE_USER', 'ROLE_ROOT']);
self::$kernel->getContainer()
->get('security.token_storage')
->setToken($token);
$this->pages = self::$kernel->getContainer()->get('app.pages');
$this->formFactory = self::$kernel->getContainer()->get('form.factory');
}
BUT BUT BUT Even if it is possible to solve that problem, the real issue in this case is, to have that $this->container->get('security.token_storage')->getToken()->getUser(); call with the Form, since this breaks the form in a test case. The pattern to prevent such a thing from happening is dependency injection, what I have missed to apply on the form type.
So the better solution would be (in the Form extending AbstractType):
public function configureOptions(OptionsResolver $resolver)
{
$this->setDefined(['user]);
}
And finally create the form like so (in Controller or TestCase)
Within a UnitTest:
$user = new User();
and in the controller:
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$form = $this->formFactory->create(TheFormType::class,
<some data object>,
['user' => $user]);
Okey so after searching for 3 hours and trying various options, I no longer have any clue how to solve this...
The situation:
Our nationwide packet deliverer (Die Post) offers a webservice for checking if an address exists.
I contacted them, received username and password for the application as well as the .wsdl-file.
I made a service reference to the downloaded file and can use the classes without problems.
Now the problem:
We have 2 other webservices which the previous programer set up with authentication and everything, I just copy pasted the code from one of the services and set everything to current one, but when I try to get a response, I always get an error (Internal Error), with no more information.
I found a way to get the last request and the only difference from the request to the one in the SoapUI (which works perfectly fine) is that, instead of "<soapenv:Header/>" it is
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://post.ch/AdressCheckerExtern/V4-01-00</Action>
</s:Header>
The current code is:
// Create Request
PostAdressChecker.AdressCheckerRequestType adrRequest = new PostAdressChecker.AdressCheckerRequestType()
{
Street = strStrasse,
HouseNbr = strHausnummer,
Zip = strPlz,
Town = strOrt,
Params = new PostAdressChecker.AdressCheckerRequestTypeParams()
{
CallUser = "TU_99660_0001",
SearchLanguage = "1",
MaxRows = "10",
SearchType = "10"
}
};
BasicHttpBinding basicBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{
ReaderQuotas = { MaxStringContentLength = int.MaxValue },
MaxReceivedMessageSize = int.MaxValue,
SendTimeout = new TimeSpan(0, 2, 0)
};
PostAdressChecker.ACHePortTypeClient client;
client = new PostAdressChecker.ACHePortTypeClient(basicBinding, new EndpointAddress(strUrl));
client.Endpoint.Behaviors.Add(new PostSigningEndpointBehavior(strUsername, strPassword));
SoapTracer RequestInterceptor = new SoapTracer();
client.Endpoint.Behaviors.Add(RequestInterceptor);
try
{
PostAdressChecker.AdressCheckerResponseType adrResponse = client.AdrCheckerExterne(adrRequest);
}
catch (Exception ex)
{
strError = ex.ToString();
}
Does anybody have an idea how to debug/solve this?
Thank you very much and best regards
in perl I do it like this. maybe this can give you some inspiration ...
sub clientFactory {
my $wsdl = XML::Compile::WSDL11->new('etc/adrCheckerExterne-V4-01-00.wsdl');
$wsdl->importDefinitions('etc/adrCheckerExterne-V4-01-00.xsd');
$wsdl->importDefinitions('etc/adrCheckerTypes-V4-01-00.xsd');
my $basic_auth = sub {
my ($request, $trace) = #_;
my $authorization = 'Basic '.
b64_encode "$adrCheckerUser:$adrCheckerPassword";
$request->header(Authorization => $authorization );
my $ua = $trace->{user_agent};
$ua->request($request);
};
return $wsdl->compileClient(
'AdrCheckerExterne',
transport_hook => $basic_auth,
aync => 1,
);
};
my $client = clientFactory;
my $check = $client->(
Params => {
MaxRows => 100,
CallUser => $adrCheckerUser,
SearchLanguage => 1,
SearchType => 1
},
FirstName => $first_name,
Name => ${last_name},
Street => ${street},
HouseNbr => ${nr},
Zip => ${zip},
Town => ${town},
HouseKey => 0,
PboxAddress => 0,
);
You need to add HouseKey = 0 to your adrRequest. This is a required input - you can just set it to 0 if you do not know it. Otherwise the service will return an error.
How I can add tags in a product using prestashop webservice api?
I need a a function in this way:
function addTagToProduct((int)$ProductId, (string)$tagname){}
The same for attachment document: what shall I pass to webservice for add those ?
I use this function for add tags to my product:
public function getTagId($Tag){
//if tag exists
$xml = $this->get(array('url' => $this->url . '/api/tags?filter[name]='.$Tag.'&limit=1'));
$resources = $xml -> children() -> children();
if(!empty($resources)){
$attributes = $resources->tag->attributes();
return $attributes['id'];
}
//if not exists, add it
$xml = $this->get(array('url' => $this->url . '/api/tags?schema=synopsis'));
$resources = $xml -> children() -> children();
unset($resources->id);
$resources->name = $Tag;
$resources->id_lang = $this->getIdLang();
$opt = array(
'resource' => 'tags',
'postXml' => $xml->asXML()
);
$xml = $this->add($opt);
return $xml->tag->id;
}
Hope it help.
I am trying to implement Tags to my posts. the user will input the tags in a textbox separated by commas.
public function addAction() {
$entityManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
$article = new Article;
$form = new ArticleForm();
$form->setHydrator(new DoctrineHydrator($entityManager,'CsnCms\Entity\Article'));
$form->bind($article);
$request = $this->getRequest();
if ($request->isPost()) {
$post = $request->getPost();
$form->setData($post);
if ($form->isValid()) {
$this->createTags($article, $post["Tags"]);
$this->prepareData($article);
$entityManager->persist($article);
$entityManager->flush();
return $this->redirect()->toRoute('csn-cms/default', array('controller' => 'article', 'action' => 'index'));
}
}
return new ViewModel(array('form' => $form));
}
in the above code i have added a class called createTags that i am planning to split the inputted tags into an array and create a new tag entity for each and then store the new tag entities in a array in the article object. Is this the correct way I should be doing this?
No, you wont be able search your pages based on tag if you store them in an array. you need to have a separated db table with columns like id,tag,pageId so you can properly search the pages with tag names.
Sorry if the question want that detailed was just wondering if I should use a filter instead (I think this would work but dont know if it is good practice)
In the end I just use the processData function
public function prepareData($article, $post) {
$separator = ",";
if($post['tagsString'] != "")
{
//Link Tags
$array = array_unique(explode($separator, $post['tagsString']));
foreach ($array as $tagString) {
$tag = $this->getEntityManager()->getRepository('Cms\Entity\Tag')->findOneBy(array('tag' => $tagString));
$link = new \Cms\Entity\LinkTagToArticle($article, $tagString, $tag);
$this->getEntityManager()->persist($link);
}
}
}
I'm trying to learn about Events in Doctrine, but when I read the docs, I get stuck at the very first line:
$evm = new EventManager();
Here I get a
PHP Fatal error: Class 'EventManager' not found
How can I solve this issue?
Here is the complete code:
use Doctrine\ORM\Tools\Setup;
require_once("Doctrine/ORM/Tools/Setup.php");
Setup::registerAutoloadPEAR();
$classLoader = new Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$paths = array();
$isDevMode = true;
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$dbParams = array("driver" => "pdo_mysql",
"host" => variable_get("dbManip_host"),
"user" => variable_get("dbManip_user"),
"password" => variable_get("dbManip_password"),
"dbname" => variable_get("dbManip_dbName"),
"charset" => "utf8");
global $entityManager_globalObject;
$entityManager_globalObject = \Doctrine\ORM\EntityManager::create($dbParams, $config);
$entityManager_globalObject->getConnection()->exec("SET NAMES UTF8");
$evm = new EventManager();
You are looking for class Doctrine\Common\EventManager.
$evm = new \Doctrine\Common\EventManager();
or
use Doctrine\Common\EventManager; // at the top of your file
$evm = new EventManager();