Product Controller doesn't transfer me to template

The add category web service works beautifully. I call my webservice, which curls into admin/category.add. My addon’s function gets control via the update_category hook and checks if the request came from my web service. If so, it outputs the category_id and halts.


function fn_web_service_integration_update_category($category_data, $category_id, $lang_code) {
if ($_REQUEST['csci']=='addcategory') {
echo $category_id."\n";
exit(0);
}
}




The problem with the update_product hook is that it hasn’t been placed at the completion of adding/updating a new product! If you are adding a new product, it transfers control after the product has been added, but not the category rows, or images. So if you transfer control at that point, and print out the id, (and halt execution so you can READ the id), you then have an incomplete product that doesn’t show on the web. At the very best in my hook function I can add a notification which gets thrown into the page which I would have to parse and find. Which is unacceptable, extremely messy, and probably not compatible with all skins etc.


$msg = $product_id."\n";
fn_set_notification('N', fn_get_lang_var('product added'), $msg, false, 'product added');




If I try to catch the execution after the total product has been added, the next hook I see is get_product_data. I can put a flag into a session variable in the product_added hook function, and then look for that in the get_product_data function which works fine. However, at that point if I try to echo out a product_id I get nothing and a page is rendered normally for some reason. This is extremely frustrating.



No hook is available for after a product is completely added for anyone to use.



There is no way to easily redirect the output a product add to a simple script to print out the id (only for webservice add, not a webpage add!).



I know I can add a template into my addons that could override the products.add’s template, but how would I then check if it was a normal webpage add and transfer control back to the original tpl file?



the view->display commands don’t seem to work for me either…



Or, how can I transfer conditionally to my own template or php file.



so much work to accomplish the simplest of tasks.

Scott,



If you are calling the add product controller (dispatch=products.add) then why don’t you just use a post controller (addson//controllers/admin/products.post.php)?



You can still capture the product_data from the $_REQUEST. It think it would simplify your life for what you’re trying to do.

Thanks, I guess I’m going to have to try that tomorrow…I’m running out of options. It just seems like the whole api for cs-cart is terribly lopsided towards modifying the output with no regard for data exchange. The creators of this should have thought bigger in terms of what the product could be, instead of shooting for smallville.

  1. there is no API - you are calling internal functions that have no guarantee of standarization or even of future compatibility
  2. it is designed to work with addons that provide their own “control”
  3. It is not designed for web services, but rather as an interactive administrative environment.



    I told you very early on in this tread that it would not be easy and that the devil is in the details. The obvious is easy, the rest takes becoming dependent on internal behavior and requires ongoing verification and maintenance at each upgrade.



    I can guarantee you it’s all possible. Just wait till you try to export/integrate/import production options and features…



    If you really wanted to develop a portable web service then you should create a “secure controller” and then establish your own API’s to the environment from there. You can eliminate the secure controller part if you are willing (which you’ve done) is to basically screen-s****e the login process and then call your controller via your established API. I.e. first curl() call does the login and session establishment. Subsequent curl()'s are your controller modes.



    You’ve actually taken it further than most I’ve watched. Most go for a specific action and ignore all the details. In my environment, I assume that the cart is for sales and presentation only. Everything that is “managed” from an product/order standpoint is managed from the back-end and then changes/modifications are integrated with the cart as the “slave”. I can manage multiple stores (carts) from a single or multiple inventory data based on different back-end “companies”. But then I started with a back-end and then found a cart I could work with to accomplish what my customers want.

Well I’m proud of myself, I created a post controller and it worked too. But again I lack the knowledge of how to control what template it is using, or how to transfer back to the regular template if it is not the web service doing the add.



So my last ditch effort before going back to direct db updates is this:



in the products post controller I am going to write a product object serialized as xml to an output directory IF the web service called the product add/update. The same will go for categories. For new orders, I will also write out the order object, serialized as xml. For tracking updates, the same. Or maybe I will just write abbreviated xml for product/category adds. At least I can then tell if my operations are successful. I have the ability on the ERP end using vb.net to deserialize back to similar objects also making it all very neat to work with.



This in fact is what I am doing from great plains right now.



I hope this will work. In the mean time, last week I had asked cscart if they could write a simple web service to add/update a product for me, and how much it would cost, and their first answer was, “Do you want a form to create a product?” huh

Then I re-explained in super fine detail exactly what I wanted, and they came back after a few days, “[FONT="]We will investigate the complexity of requested project and contact you with detailed answer at the first opportunity.” So It’ll be curious to see what they say.





[/FONT]

[quote]

I lack the knowledge of how to control what template it is using,

[/quote]

Not sure why you want to use a template at all for a web service operation. When the service completes, just echo your output so curl() will see it and exit and/or redirect back to admin.php.



something akin (pseudo code) to:

Called as …admin.php?dispatch=ws.product.add (assumes you have done appropriate authentication of the caller)

or

admin.php?dispatch=ws.product.update.abc-widget



In addons/ws/controllers/admin/controllers/admin/ws.php


if( !defined('AREA') ) die('Access denied');

if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
switch($mode) {
case 'product':
switch($action) {
case 'add':
$result_ar = array();
$p_data = empty($_REQUEST['product_data']) ? array() : $_REQUEST['product_data'];
foreach($p_data as $upc => $p_info))
$result_ar[$upc] =some_api_to_add_product($p_info);
echo implode("\n", $result_ar);
exit;
case 'update':
$upc = empty($dispatch_extra) : '' : $dispatch_extra;
$result_ar = array();
$p_data = empty($_REQUEST['product_data'][$upc]) ? array() : $_REQUEST['product_data'][$upc];
if( $upc && $p_data ) {
$result_ar[$upc] = some_api_to_update_product($upc, $p_info);
echo implode("\n", $result_ar);
exit;
}
break;
case 'category':
switch($action) {
case 'add':
.....
}
break;
}
break;
}
} else { // Not POST, do whatever
...
}
if( !empty($redirect_url) )
redirect($redirect_url);
else
redirect($index_script);




Or, for the ‘add’, you could do an http request to admin.php?products.update but then you’d have to screen-s****e the result before returning to your caller.

I’m using NuSoap to maintain compatibility with .Net and any other languages that might want to interface, I cannot call the controller as the webservice, .net or other soap web service clients wouldn’t recognize that. NuSoap automatically creates the WSDL that is needed.



And as far as directly echoing, if I could figure a way to call the fn_update_product directly from my page, then I could do that. But I don’t think the function will work like that because a whole lot of foundation pages had to load prior to code execution getting to that point.



The webservice itself is calling the controller, and I need output back from the controller so the webservice can pass it on as a return value.



I will have to investigate calling a controller from dotnet. That would be pretty simple. Then my controller could directly call the add or update product function like you show. Which eliminates the output problem. I really want a true SOAP based webservice though if I can do it.


[quote name=‘tbirnseth’]Not sure why you want to use a template at all for a web service operation. When the service completes, just echo your output so curl() will see it and exit and/or redirect back to admin.php.



something akin (pseudo code) to:

Called as …admin.php?dispatch=ws.product.add (assumes you have done appropriate authentication of the caller)

or

admin.php?dispatch=ws.product.update.abc-widget



In addons/ws/controllers/admin/controllers/admin/ws.php


if( !defined('AREA') ) die('Access denied');

if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
switch($mode) {
case 'product':
switch($action) {
case 'add':
$result_ar = array();
$p_data = empty($_REQUEST['product_data']) ? array() : $_REQUEST['product_data'];
foreach($p_data as $upc => $p_info))
$result_ar[$upc] =some_api_to_add_product($p_info);
echo implode("\n", $result_ar);
exit;
case 'update':
$upc = empty($dispatch_extra) : '' : $dispatch_extra;
$result_ar = array();
$p_data = empty($_REQUEST['product_data'][$upc]) ? array() : $_REQUEST['product_data'][$upc];
if( $upc && $p_data ) {
$result_ar[$upc] = some_api_to_update_product($upc, $p_info);
echo implode("\n", $result_ar);
exit;
}
break;
case 'category':
switch($action) {
case 'add':
.....
}
break;
}
break;
}
} else { // Not POST, do whatever
...
}
if( !empty($redirect_url) )
redirect($redirect_url);
else
redirect($index_script);
Or, for the ‘add’, you could do an http request to admin.php?products.update but then you’d have to screen-s****e the result before returning to your caller.[/quote]

All the issues you discuss is why I chose to use the REST protocol (or close to it) rather than SOAP. While SOAP has some advantages for portabllity (byte order, data size, etc.) it gives nothing (other than large transactions) when the data is primarily “string data’” versus data structures and differing types REST is simple and basically matches the cart’s controller mechanism. I.e. give scope in the parameters and data via POST (not further structured in XML)…



I prefer performance versus layers and layers of protocols to perform specific transactions. If I were trying to provide a service that utilized more binary data, then I would look closer into the overhead of SOAP to take advantage of its strengths. The difference of adding 5000 products using SOAP versus REST will be signficant if you can even get the SOAP to not time out due to the huge size of the XML that would be created.

[quote name=‘tbirnseth’]All the issues you discuss is why I chose to use the REST protocol (or close to it) rather than SOAP. While SOAP has some advantages for portabllity (byte order, data size, etc.) it gives nothing (other than large transactions) when the data is primarily “string data’” versus data structures and differing types REST is simple and basically matches the cart’s controller mechanism. I.e. give scope in the parameters and data via POST (not further structured in XML)…



I prefer performance versus layers and layers of protocols to perform specific transactions. If I were trying to provide a service that utilized more binary data, then I would look closer into the overhead of SOAP to take advantage of its strengths. The difference of adding 5000 products using SOAP versus REST will be signficant if you can even get the SOAP to not time out due to the huge size of the XML that would be created.[/quote]



You are correct about SOAP being a huge string. I do kind of like the layers, but they aren’t needed. And I’m shocked to learn that REST is actually a sort of “standard” too… That makes it much easier for me to switch to that since all it really is an http post, but I can say I’m following a certain standard.



The only thing I can’t get the cscart to do is fire my web_service_integration.php file that is sitting at addons/controllers/admin/web_service_integration.php by calling cscart/admin.php?dispatch=web_service_integration.add for example though. Maybe it doesn’t like the underscores. My addin id is ‘web_service_integration’, but my addon name is ‘Web Service Integration’.



Maybe I’ll rename all to ws and see if I can get it to work that way.



Thanks so much for all the information.



ws
Web Service Integration
1
1
active





That is my addon xml.

my addon is in cscart/addons/ws/controllers/admin/ws.php



also in that directory is a products.post.php which gets fired if I add a product.



but I still cannot call

[url]http://webserv01.gva-twn.com/cscart/admin.php?dispatch=ws.add&product_id=333[/url]



I get page not found. When I get home later I will trace the entire process through the code to find out what is going wrong. It is still amazing the other stuff all works.