SocialEngine: getDbTable() vs. getItemTable() - zend-framework

I have often seen tables are retrieved in SocialEngine using Engine_Api::_()->getDbTable().
For example:
$usersTbl = Engine_Api::_()->getDbTable('users','user');
$row = $usersTbl->createRow();
$row->user_id = $user->getIdentity();
$row->phone_number = $phoneNumber;
$row->save();
However, I also see that SocialEngine has used Engine_Api::_()->getItemTable in many places. For example:
$table = Engine_Api::_()->getItemTable($type);
$row = $table->createRow();
foreach($params as $key=>$value) {
if(isset($row->$key)) {
$row->key = $value;
}
}
$row->save();
What is the main difference between these two types of accesses, if any, and when is each one used?

/application/libraries/Engine/
Engine folder is SocialEngine CMS on top of zend, here you find all the function definitions
/application/modules/moduleName/settings/manifest.php [Here you add items, in a module]
when application is loaded, all manifest files are scanned and items are loaded.
getItemTable can only load, DbTable class when item is defined.
where as getDbTable() can be used for tables which are not used as Items.

Related

Magento 2: Need to re-save all products after re-assigning source

so I deactived all MSI-related modules and found out that it still needed it for another module, so I activated it again.
Then the default source that was created by the data-migration from M1 to M2 was gone after that.
So I created a new source and added all products to that source, however all the products were still 'out of stock' on the frontend. After re-saving a product, it is displayed properly on the frontend.
Therefore I need to re-save all products. Is there a fast way to do so or can I do something else?
Btw: I tried reindexing, upgrading etc.
Thanks
Write a CLI command to save all products again
$storeId = 1;
$productCollection = $this->collectionFactory->create()
->addAttributeToSelect('id')
->addStoreFilter($storeId)
->load();
$i = 1;
foreach ($productCollection as $product) {
$productId = $product->getId();
$product = $this->product->create()->load($productId);
$product->save();
echo $i.". Saved product ".$product->getName()." with product id ".$productId. "\n";
$i++;
}

Magento 2 - Split an order in two parts

I am trying to make a functionality to split an order in 2 which has 2 different Seller Item in my custom module.
Do you have any idea about how to do this pro-grammatically please ?
Reference link split orders in magento
Reference link Magento - 2
Is possible split the order by seller attribute. You just need to intercept the placeOrder function using around action plugin.
There, you can map all of the items into cart and create a new order for each product you want.
Please refer (In this case, split by product SKU getSku, you can change for any attribute):
public function aroundPlaceOrder(
\Magento\Quote\Model\QuoteManagement $subject,
callable $proceed,
$cartId,
$paymentMethod = null
) {
$quote = $this->quoteRepository->getActive($cartId);
$quotes = [];
foreach ($quote->getAllVisibleItems() as $item) {
$quotes[$item->getProduct()->getSku()][] = $item;
}
foreach ($quotes as $groups => $items) {
...
Also, you can take a look here:
https://github.com/magestat/magento2-split-order/blob/develop/Plugin/SplitQuote.php
Thanks!

Get Line Items in an Invoice logic hook in SuiteCRM

Via a logic hook I'm trying to update fields of my products, after an invoice has been saved.
What I understand so far is, that I need to get the invoice related AOS_Products_Quotes and from there I could get the products, update the required fields and save the products. Does that sound about right?
The logic hook is being triggered but relationships won't load.
function decrement_stocks ( $bean, $event, $arguments) {
//$bean->product_value_c = $bean->$product_unit_price * $bean->product_qty;
$file = 'custom/modules/AOS_Invoices/decrement.txt';
// Get the Invoice ID:
$sInvoiceID = $bean->id;
$oInvoice = new AOS_Invoices();
$oInvoice->retrieve($sInvoiceID);
$oInvoice->load_relationship('aos_invoices_aos_product_quotes');
$aProductQuotes = $oInvoice->aos_invoices_aos_product_quotes->getBeans();
/*
$aLineItemslist = array();
foreach ($oInvoice->aos_invoices_aos_product_quotes->getBeans() as $lineitem) {
$aLineItemslist[$lineitem->id] = $lineitem;
}
*/
$sBean = var_export($bean, true);
$sInvoice = var_export($oInvoice, true);
$sProductQuotes = var_export($aProductQuotes, true);
$current = $sProductQuotes . "\n\n\n------\n\n\n" . $sInvoice . "\n\n\n------\n\n\n" . $sBean;
file_put_contents($file, $current);
}
The invoice is being retrieved just fine. But either load_relationship isn't doing anything ($sInvoice isn't changing with or without it) and $aProductQuotes is Null.
I'm working on SuiteCRM 7.8.3 and tried it on 7.9.1 as well without success. What am I doing wrong?
I'm not familiar with SuiteCRM specifics, however I'd always suggest to check:
Return value of retrieve(): bean or null?
If null, then no bean with the given ID was found.
In such case $oInvoice would stay empty (Your comment suggests that's not the case here though)
Return value of load_relationship(): true (success) or false (failure, check logs)
And I do wonder, why don't you use $bean?
Instead you seem to receive another copy/reference of $bean (and calling it $oInvoice)? Why?
Or did you mean to receive a different type bean that is somehow connected to $bean?
Then its surely doesn't have the same id as $bean, unless you specifically coded it that way.

Zend framework 1.11 Gdata Spreadsheets insertRow very slow

I'm using insertRow to populate an empty spreadsheet, it starts off taking about 1 second to insert a row and then slows down to around 5 seconds after 150 rows or so.
Has anyone experienced this kind of behaviour?
There aren't any calculations on the data in the spreadsheet that could be getting longer with more data.
Thanks!
I'll try to be strict.
If you take a look at class "Zend_Gdata_Spreadsheets" you figure that the method insertRow() is written in a very not optimal way. See:
public function insertRow($rowData, $key, $wkshtId = 'default')
{
$newEntry = new Zend_Gdata_Spreadsheets_ListEntry();
$newCustomArr = array();
foreach ($rowData as $k => $v) {
$newCustom = new Zend_Gdata_Spreadsheets_Extension_Custom();
$newCustom->setText($v)->setColumnName($k);
$newEntry->addCustom($newCustom);
}
$query = new Zend_Gdata_Spreadsheets_ListQuery();
$query->setSpreadsheetKey($key);
$query->setWorksheetId($wkshtId);
$feed = $this->getListFeed($query);
$editLink = $feed->getLink('http://schemas.google.com/g/2005#post');
return $this->insertEntry($newEntry->saveXML(), $editLink->href, 'Zend_Gdata_Spreadsheets_ListEntry');
}
In short, it loads your whole spreadsheet just in order to learn this value $editLink->href in order to post new row into your spreadsheet.
The cure is to avoid using this method insertRow.
Instead, get your $editLink->href once in your code and then insert new rows each time by reproducing the rest of behaviour of this method. I.e, in your code instead of $service->insertRow() use following:
//get your $editLink once:
$query = new Zend_Gdata_Spreadsheets_ListQuery();
$query->setSpreadsheetKey($key);
$query->setWorksheetId($wkshtId);
$query->setMaxResults(1);
$feed = $service->getListFeed($query);
$editLink = $feed->getLink('http://schemas.google.com/g/2005#post');
....
//instead of $service->insertRow:
$newEntry = new Zend_Gdata_Spreadsheets_ListEntry();
$newCustomArr = array();
foreach ($rowData as $k => $v) {
$newCustom = new Zend_Gdata_Spreadsheets_Extension_Custom();
$newCustom->setText($v)->setColumnName($k);
$newEntry->addCustom($newCustom);
}
$service->insertEntry($newEntry->saveXML(), $editLink->href, 'Zend_Gdata_Spreadsheets_ListEntry');
Don't forget to encourage this great answer, it costed me few days to figure out. I think ZF is great however sometimes you dont want to rely on their coode too much when it comes to resources optimization.

Zend_Translate Strategy for a huge grown web site

since I'm thinking in a good way to handle translation did part of a implementation and going toward a concept that still don't know if it's good and I would like to share it and get the pros and cons of it with someone that think it's a good point to explore.
The architecture is meant to work in a componentized site with translations comming from Actions, Forms, Views, View_Helpers and even Action_Helpers.
The ideis is simple:
Zend_Translate will the got from registry in every component and will receive __FILE__ as parameter. Since it was initialized with 'clear' on bootstrap it will be possible to load just the array file that correspont to this calling compoment. When comes to the missing translations they will be logged to a database (to avoid log duplicates) and/or be added to the corresponding array file in the remaining untranslated languages (as well as have the array file created) with a null value where it's is not set yet.
My guess is that using cache and specializing Translate i can ignore the translations that are set with null (by the addition made before) without log it again (displayin just the key) it will overhead a little bit the firt call for a large untraslated page and then gain performance later as well as maintainability and work ability with the automation of the translation process that would like to supply for the user.
But after that I was figuring out that I could build a array with the missing translations from every component to be save at the request end, and that is my question.
Had you folks had some experience with this that could be helpful to determine what's the best strategy?
bootstrap
protected function _initLocale() {
$translateSession = new Zend_Session_Namespace('translate');
$locale = isset($translateSession->locale) ? $translateSession->locale : 'auto';
try {
$zendLocale = new Zend_Locale($locale);
} catch (Zend_Locale_Exception $e) {
$zendLocale = new Zend_Locale('en_US');
}
Zend_Registry::set('Zend_Locale', $zendLocale);
$translate = new Engine_Translate('customarray', array('clear'));
$logger = Engine_Logger::getLogger();
$translate->setOptions( array('log2db' => $logger ,'log' => $logger, 'logPriority' => Zend_Log::ALERT, 'logUntranslated' => true));
Zend_Registry::set('Zend_Translate', $translate);
}
simple library
function getAvailableTranslationLanguages() {
return array("pt_BR"=>"Português","en_US"=>"Inglês");
}
function setTranslationLanguage($code) {
$translateSession = new Zend_Session_Namespace('translate');
$translateSession->locale = $code;
}
function getTranslator($file) {
$relative = str_replace(APPLICATION_PATH, '', $file);
$code = Zend_Registry::get('Zend_Locale');
$path = APPLICATION_PATH . '\\lang\\' . $code . $relative;
$translator = Zend_Registry::get('Zend_Translate');
try {
$translator->addTranslation($path, $code);
} catch (Exception $e) {
createTranslationFile($path);
}
return $translator;
}
function createTranslationFile($path) {
if(!file_exists(dirname($path)))
mkdir(dirname($path), 0777, true);
$file = fopen($path, 'w');
if($file) {
$stringData = "<?php\n return array(\n );";
fwrite($file, $stringData);
fclose($file);
} else {
$logger = Engine_Logger::getLogger();
$logger->info(Engine_Logger::get_string('ERRO ao abrir arquivo de tradução: ' . $path));
}
}
The use
class App_Views_Helpers_Loginbox extends Zend_View_Helper_Abstract
{
public function loginbox() {
$translate = getTranslator(__FILE__);
Translation resources
If I understand correctly, you want to create new adapter for each action helper/ view helper/ etc. This is IMO wrong and hugely ineffective. I would stick the translations to URLs. Make one common.php for translations used everywhere, module.php for module-specific and page-name.php for page specific translation. Then array_merge them together and create one adapter in Bootstrap. Then cache it (using URL as the cache key) somewhere - prefferably in memory (=memcached, apc). That way you would create the translate adapter from cache very effectively - only load+unserialize. Many translations (for each helper) means many disc accesses, means lower speed and scalability as disc will soon be the bottleneck.