Magento API V2 - add an additional attribute to API response - api

I'm using the Magento API V2.
When I call salesOrderCreditmemoInfo, I get a response with the credit memo details and a list of the products associated with the order.
But in the list of product items there is no product_type attribute.
I want to manually edit the response to add this attribute.
I tried editing:
app\code\core\Mage\Sales\Model\Order\Creditmemo\Api.php
And replaced:
public function info($creditmemoIncrementId)
{
...
$result['items'] = array();
foreach ($creditmemo->getAllItems() as $item) {
$result['items'][] = $this->_getAttributes($item, 'creditmemo_item');
}
With the following - (basically appending an extra attribute to the array):
public function info($creditmemoIncrementId)
{
...
$result['items'] = array();
foreach ($creditmemo->getAllItems() as $item) {
$product_type = '1'; //test value to check if works
$attribs = $this->_getAttributes($item, 'creditmemo_item');
$attribs['product_type'] = $product_type;
$result['items'][] = $attribs;
}
When I do mage::log($result), the extra attribute seems to be added correctly to the array.
(also indicating that this function is the one getting called)
But it has no impact on the actual API response.
Am I totally looking in the wrong place or is there something else I need to update?

Since You were using SOAP V2, you should update the wsdl.xml to get the output.
For your case it is product_type and refresh cache on server. /tmp to load the new wsdl.xml that already updated. don't forget to go to System -> Cache Management clear all cache.

Related

Shopware 6 custom element type image not showing any data on storefront

I have created my component to add some desired config fields in Shopware 6. Everything is working fine but one problem that is image is looking as it is being saved in the administration but is not showing any src or else in dump.
And here is my dump preiew having #data null.
can anyone tell what should I do else here?
I will be very thankful.
There is a guide in the docs that explains exactly what your case is.
You can likely extend the \Shopware\Core\Content\Media\Cms\ImageCmsElementResolver and override the getType function:
public function getType(): string
{
return 'my-component-name';
}
The important part of the default ImageCmsElementResolver is the loading the media information. For that you also need in your CMS element resolver. I explain some parts of the existing ImageCmsElementResolver so you can see which steps you need:
public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
{
// read the configuration, that is defined in the Admin JS. Likely also media for you
$mediaConfig = $slot->getFieldConfig()->get('media');
// if this config is NOT containing useful info
if (
$mediaConfig === null
|| $mediaConfig->isMapped()
|| $mediaConfig->isDefault()
|| $mediaConfig->getValue() === null
) {
// return nothing
return null;
}
// otherwise use the configured value as mediaId to load the media entry from the database
$criteria = new Criteria([$mediaConfig->getStringValue()]);
$criteriaCollection = new CriteriaCollection();
$criteriaCollection->add('media_' . $slot->getUniqueIdentifier(), MediaDefinition::class, $criteria);
// return the criterias to execute later, when all needed entities for the CMS page are fetched
return $criteriaCollection;
}
Now the data is fetched and as next step you need to put it into a variable accessible from the Twig template. For this you write into the same CMS element resolver this:
public function enrich(CmsSlotEntity $slot, ResolverContext $resolverContext, ElementDataCollection $result): void
{
$config = $slot->getFieldConfig();
$image = new ImageStruct();
// this is important for accessing data in Twig
$slot->setData($image);
// read the config again
$mediaConfig = $config->get('media');
// if the configuration looks promising
if ($mediaConfig && $config->isStatic() && $mediaConfig->getValue()) {
$image->setMediaId($config->getStringValue());
// look up the media from the entity loading step
$searchResult = $result->get('media_' . $slot->getUniqueIdentifier());
if (!$searchResult) {
return;
}
/** #var MediaEntity|null $media */
$media = $searchResult->get($config->getValue());
// if we do not have a media, then skip it
if (!$media) {
return;
}
// set the media entity to the slot data we just assigned to the slot
$image->setMedia($media);
}
}
After that you should have more info in the slot variable in Twig to embed a media.

How to generate a single PDF using Rotativa from a View which has different dynamic headers in ASP.Net MVC?

I am using Rotativa to generate a single PDF file for single invoice, in Asp.Net MVC application. I am using the command --header-html with CustomSwitches of ViewAsPdf to include header for each page of an Invoice as follows,
public ActionResult GenerateSingleInvoicePDF(string invoiceId)
{
var invoiceViewModel = new InvoicePDFModel();
... // get content from database;
...
...
ViewBag.InvoiceDetail = invoiceViewModel;
string customSwitches = string.Format("--print-media-type --allow {0} --header-html {0} --page-offset \"0\" --header-spacing \"1\" ", Url.Action("InvoiceHeader", "Order", new { invNumber =
invoiceViewModel.invNo, invDate = invoiceViewModel.InvoiceDateString, shippAddr = invoiceViewModel.DeliveryAddr, billingAddress = invoiceViewModel.BillingAddr }, "http"));
return new ViewAsPdf("~/SingleInvoiceView.cshtml")
{
FileName = "SingleInvoice.pdf",
PageSize = Size.A4,
CustomSwitches = customSwitches
};
}
This works perfectly without any issue. Now my need is how to generate a single PDF for multiple invoice. I tried the above code for multiple invoice as follows,
public ActionResult GenerateMultipleInvoicePDF(string invoiceIds)
{
var invoiceList = new List<InvoicePDFModel>
... // get list of content from database;
...
...
ViewBag.InvoiceList = invoiceList;
string customSwitches = // don't know how to define header view for multiple invoice.
return new ViewAsPdf("~/MultiInvoiceView.cshtml")
{
FileName = "MultiInvoice.pdf",
PageSize = Size.A4,
CustomSwitches = customSwitches
};
}
But I am stuck at the header part. Because, header content varies for each invoice. Any suggestions how to do this?
For your specific case, taking a look at your individual invoice code
Url.Action("InvoiceHeader", "Order", new { invNumber =
invoiceViewModel.invNo, invDate = invoiceViewModel.InvoiceDateString, shippAddr = invoiceViewModel.DeliveryAddr, billingAddress = invoiceViewModel.BillingAddr }, "http")
Maybe it would be a good idea to take all the parameters you are sending to the view and store them inside a model. This model could keep a list or collection of classes or models, each of them with the same pack of parameters that you send for an individual invoice. Then, on the view, you might be able to determine, depending on your requirements, which parameters you must specify for each page.
Bearing in mind that Rotativa uses WkHtmlToPdf, and as you can chek in this, an other posts, the oficial documentation sets that the page number, among other parameters, is send to the header/footer.
Could be tricky, but this means you might be able to achieve what you are looking for, following these steps:
Generate MVC action and asociated view, to generate the header, accepting the model you wish.
Inside the view, access QueryString parameter for page number, so this way you can identify which invoice you are printing (supossing that each invoice prints no more and no less than one page).
Using the collection of classes from your model, access by index the particular invoice that matches the page number from the previous step, and write the view according to the parameters that apply for the current invoice.

get the sys_file_metadata values using typo3 repository methods

I am building an extension using typo3. I got stuck at one point. That is, I need the sys_file_metadata value along with sys_file informations. I am getting sys_file informations using repository methods. But not getting the metadata informations like title, description.
Can anyone help me to find a repository method to fetch metadata informations using repository methods?
$storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository'); // create instance to storage repository
$storage = $storageRepository->findByUid(2); // get file storage with uid 1 (this should by default point to your fileadmin/ directory)
$folder = $storage->getFolder('/Audios/',false);
$files = $storage->getFilesInFolder($folder);
foreach ($files as $key => $value) {
$array_file = $files[$key]->toArray();
$uid = $array_file['uid'];
$array['name'] = $array_file['name'];
$array['extension'] = $array_file['extension'];
}
I found the answer. We can use the method
$value->_getMetaData();
To get the specified properties, we can use
$value->getProperty('description');

Datatables: How to reload server-side data with additional params

I have a table which gets its data server-side, using custom server-side initialization params which vary depending upon which report is produced. Once the table is generated, the user may open a popup in which they can add multiple additional filters on which to search. I need to be able to use the same initialization params as the original table, and add the new ones using fnServerParams.
I can't figure out how to get the original initialization params using the datatables API. I had thought I could get a reference to the object, get the settings using fnSettings, and pass those settings into a new datatables instance like so:
var oSettings = $('#myTable').dataTable().fnSettings();
// add additional params to the oSettings object
$('#myTable').dataTable(oSettings);
but the variable returned through fnSettings isn't what I need and doesn't work.
At this point, it seems like I'm going to re-architect things so that I can pass the initialization params around as a variable and add params as needed, unless somebody can steer me in the right direction.
EDIT:
Following tduchateau's answer below, I was able to get partway there by using
var oTable= $('#myTable').dataTable(),
oSettings = oTable.fnSettings(),
oParams = oTable.oApi._fnAjaxParameters(oSettings);
oParams.push('name':'my-new-filter', 'value':'my-new-filter-value');
and can confirm that my new serverside params are added on to the existing params.
However, I'm still not quite there.
$('#myTable').dataTable(oSettings);
gives the error:
DataTables warning(table id = 'myTable'): Cannot reinitialise DataTable.
To retrieve the DataTables object for this table, please pass either no arguments
to the dataTable() function, or set bRetrieve to true.
Alternatively, to destroy the old table and create a new one, set bDestroy to true.
Setting
oTable.bRetrieve = true;
doesn't get rid of the error, and setting
oSettings.bRetrieve = true;
causes the table to not execute the ajax call. Setting
oSettings.bDestroy = true;
loses all the custom params, while setting
oTable.bDestroy = true;
returns the above error. And simply calling
oTable.fnDraw();
causes the table to be redrawn with its original settings.
Finally got it to work using fnServerParams. Note that I'm both deleting unneccessary params and adding new ones, using a url var object:
"fnServerParams": function ( aoData ) {
var l = aoData.length;
// remove unneeded server params
for (var i = 0; i < l; ++i) {
// if param name starts with bRegex_, sSearch_, mDataProp_, bSearchable_, or bSortable_, remove it from the array
if (aoData[i].name.search(/bRegex_|sSearch_|mDataProp_|bSearchable_|bSortable_/) !== -1 ){
aoData.splice(i, 1);
// since we've removed an element from the array, we need to decrement both the index and the length vars
--i;
--l;
}
}
// add the url variables to the server array
for (i in oUrlvars) {
aoData.push( { "name": i, "value": oUrlvars[i]} );
}
}
This is normally the right way to retrieve the initialization settings:
var oSettings = oTable.fnSettings();
Why is it not what you need? What's wrong with these params?
If you need to filter data depending on your additional filters, you can complete the array of "AJAX data" sent to the server using this:
var oTable = $('#myTable').dataTable();
var oParams = oTable.oApi._fnAjaxParameters( oTable );
oParams.push({name: "your-additional-param-name", value: your-additional-param-value });
You can see some example usages in the TableTools plugin.
But I'm not sure this is what you need... :-)

Get product link from Magento API

I am new to Magento and using their API. I need to be able to get the product url from the API call. I see that I can access the url_key and url_path, but unfortunately that's not necessarily what the URL for the product is (ie it may be category/my-product-url.html) where url_key would contain my-product-url and url_path would only contain my-product-url.html. Further complicating things, it may even be /category/sub-category/my-product-url.html. So, how would I get the full url with the category and everything as it is setup in the url rewrite information? Seems like this should come with the product information from the product.info api call but it doesn't.
Magento Product api does not provide such functionality
Although there are easy ways to extend specific API in custom modules, but here is the quickest way if you don't want to write a custom module ( as i think it's difficult for a new magento developer).
Copy the original product API-class from the core to the local folder before editing anything (that way your Magento installation stays "update-save").
copy Api.php from:app/code/core/Mage/Catalog/Model/Product/Api.php
to:app/code/local/Mage/Catalog/Model/Product/Api.php
Now change the info method within the copied file to include the full_url. Add the following line to the $result-array. (Make sure to set necessary commas at the end of the array-lines.)
'full_url' => $product->getProductUrl(),
Your resulting method code should look like:
public function info($productId, $store = null, $attributes = null, $identifierType = null)
{
$product = $this->_getProduct($productId, $store, $identifierType);
$result = array( // Basic product data
'product_id' => $product->getId(),
'sku' => $product->getSku(),
'set' => $product->getAttributeSetId(),
'type' => $product->getTypeId(),
'categories' => $product->getCategoryIds(),
'websites' => $product->getWebsiteIds(),
'full_url' => $product->getProductUrl(),
);
foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
if ($this->_isAllowedAttribute($attribute, $attributes)) {
$result[$attribute->getAttributeCode()] = $product->getData(
$attribute->getAttributeCode());
}
}
return $result;
}
Afterwards you can call product.info and use the full_url field via the API.
Well actually even your path is wrong, the one he is referring to is
app\code\core\Mage\Catalog\Model\Product\Product.php