How to Programmatically place order in opencart - opencart2.x

I am new to opencart. And now i am working on the order module.The concept is i have to place order externally. So as in the controller/checkout/confirm.php order placement i have placed the order. The order also successfully stored at the order table. But the problem is, the order is not shown at the admin page. I have searched lot for this issue, finally i found that the order is not placed properly.
My code is,
public function index() {
$redirect = '';
$this->load->model('account/address');
$address = $this->model_account_address->getAddress($this->customer->getAddressId());
if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
$redirect = $this->url->link('checkout/cart');
}
// Validate minimum quantity requirements.
$products = $this->cart->getProducts();
foreach ($products as $product) {
$product_total = 0;
foreach ($products as $product_2) {
if ($product_2['product_id'] == $product['product_id']) {
$product_total += $product_2['quantity'];
}
}
if ($product['minimum'] > $product_total) {
$redirect = $this->url->link('checkout/cart');
break;
}
}
if (!$redirect) {
$order_data = array();
$order_data['totals'] = array();
$total = 0;
$taxes = $this->cart->getTaxes();
$this->load->model('extension/extension');
$sort_order = array();
$results = $this->model_extension_extension->getExtensions('total');
foreach ($results as $key => $value) {
$sort_order[$key] = $this->config->get($value['code'] . '_sort_order');
}
array_multisort($sort_order, SORT_ASC, $results);
foreach ($results as $result) {
if ($this->config->get($result['code'] . '_status')) {
$this->load->model('total/' . $result['code']);
$this->{'model_total_' . $result['code']}->getTotal($order_data['totals'], $total, $taxes);
}
}
$sort_order = array();
foreach ($order_data['totals'] as $key => $value) {
$sort_order[$key] = $value['sort_order'];
}
array_multisort($sort_order, SORT_ASC, $order_data['totals']);
$this->load->language('checkout/checkout');
$order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
$order_data['store_id'] = $this->config->get('config_store_id');
$order_data['store_name'] = $this->config->get('config_name');
if ($order_data['store_id']) {
$order_data['store_url'] = $this->config->get('config_url');
} else {
$order_data['store_url'] = HTTP_SERVER;
}
if ($this->customer->isLogged()) {
$this->load->model('account/customer');
$customer_info = $this->model_account_customer->getCustomer($this->customer->getId());
$order_data['customer_id'] = $this->customer->getId();
$order_data['customer_group_id'] = $customer_info['customer_group_id'];
$order_data['firstname'] = $customer_info['firstname'];
$order_data['lastname'] = $customer_info['lastname'];
$order_data['email'] = $customer_info['email'];
$order_data['telephone'] = $customer_info['telephone'];
$order_data['fax'] = $customer_info['fax'];
$order_data['custom_field'] = unserialize($customer_info['custom_field']);
} elseif (isset($this->session->data['guest'])) {
$order_data['customer_id'] = 0;
$order_data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
$order_data['firstname'] = $this->session->data['guest']['firstname'];
$order_data['lastname'] = $this->session->data['guest']['lastname'];
$order_data['email'] = $this->session->data['guest']['email'];
$order_data['telephone'] = $this->session->data['guest']['telephone'];
$order_data['fax'] = $this->session->data['guest']['fax'];
$order_data['custom_field'] = $this->session->data['guest']['custom_field'];
}
$order_data['payment_firstname'] = $address['firstname'];
$order_data['payment_lastname'] = $address['lastname'];
$order_data['payment_company'] = $address['company'];
$order_data['payment_address_1'] = $address['address_1'];
$order_data['payment_address_2'] = $address['address_2'];
$order_data['payment_city'] = $address['city'];
$order_data['payment_postcode'] = $address['postcode'];
$order_data['payment_zone'] = $address['zone'];
$order_data['payment_zone_id'] = $address['zone_id'];
$order_data['payment_country'] = $address['country'];
$order_data['payment_country_id'] = $address['country_id'];
$order_data['payment_address_format'] = $address['address_format'];
$order_data['payment_custom_field'] = $address['custom_field'];
if (isset($this->session->data['payment_method']['title'])) {
$order_data['payment_method'] = $this->session->data['payment_method']['title'];
} else {
$order_data['payment_method'] = '';
}
if (isset($this->session->data['payment_method']['code'])) {
$order_data['payment_code'] = $this->session->data['payment_method']['code'];
} else {
$order_data['payment_code'] = '';
}
if ($this->cart->hasShipping()) {
$order_data['shipping_firstname'] = $address['firstname'];
$order_data['shipping_lastname'] = $address['lastname'];
$order_data['shipping_company'] = $address['company'];
$order_data['shipping_address_1'] = $address['address_1'];
$order_data['shipping_address_2'] = $address['address_2'];
$order_data['shipping_city'] = $address['city'];
$order_data['shipping_postcode'] = $address['postcode'];
$order_data['shipping_zone'] = $address['zone'];
$order_data['shipping_zone_id'] = $address['zone_id'];
$order_data['shipping_country'] = $address['country'];
$order_data['shipping_country_id'] = $address['country_id'];
$order_data['shipping_address_format'] = $address['address_format'];
$order_data['shipping_custom_field'] = $address['custom_field'];
if (isset($this->session->data['shipping_method']['title'])) {
$order_data['shipping_method'] = $this->session->data['shipping_method']['title'];
} else {
$order_data['shipping_method'] = '';
}
if (isset($this->session->data['shipping_method']['code'])) {
$order_data['shipping_code'] = $this->session->data['shipping_method']['code'];
} else {
$order_data['shipping_code'] = '';
}
} else {
$order_data['shipping_firstname'] = '';
$order_data['shipping_lastname'] = '';
$order_data['shipping_company'] = '';
$order_data['shipping_address_1'] = '';
$order_data['shipping_address_2'] = '';
$order_data['shipping_city'] = '';
$order_data['shipping_postcode'] = '';
$order_data['shipping_zone'] = '';
$order_data['shipping_zone_id'] = '';
$order_data['shipping_country'] = '';
$order_data['shipping_country_id'] = '';
$order_data['shipping_address_format'] = '';
$order_data['shipping_custom_field'] = array();
$order_data['shipping_method'] = '';
$order_data['shipping_code'] = '';
}
$order_data['products'] = array();
foreach ($this->cart->getProducts() as $product) {
$option_data = array();
foreach ($product['option'] as $option) {
$option_data[] = array(
'product_option_id' => $option['product_option_id'],
'product_option_value_id' => $option['product_option_value_id'],
'option_id' => $option['option_id'],
'option_value_id' => $option['option_value_id'],
'name' => $option['name'],
'value' => $option['value'],
'type' => $option['type']
);
}
$order_data['products'][] = array(
'product_id' => $product['product_id'],
'name' => $product['name'],
'model' => $product['model'],
'option' => $option_data,
'download' => $product['download'],
'quantity' => $product['quantity'],
'subtract' => $product['subtract'],
'price' => $product['price'],
'total' => $product['total'],
'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
'reward' => $product['reward']
);
}
// Gift Voucher
$order_data['vouchers'] = array();
if (!empty($this->session->data['vouchers'])) {
foreach ($this->session->data['vouchers'] as $voucher) {
$order_data['vouchers'][] = array(
'description' => $voucher['description'],
'code' => substr(md5(mt_rand()), 0, 10),
'to_name' => $voucher['to_name'],
'to_email' => $voucher['to_email'],
'from_name' => $voucher['from_name'],
'from_email' => $voucher['from_email'],
'voucher_theme_id' => $voucher['voucher_theme_id'],
'message' => $voucher['message'],
'amount' => $voucher['amount']
);
}
}
$order_data['comment'] = "";
$order_data['total'] = $total;
if (isset($this->request->cookie['tracking'])) {
$order_data['tracking'] = $this->request->cookie['tracking'];
$subtotal = $this->cart->getSubTotal();
// Affiliate
$this->load->model('affiliate/affiliate');
$affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
if ($affiliate_info) {
$order_data['affiliate_id'] = $affiliate_info['affiliate_id'];
$order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
} else {
$order_data['affiliate_id'] = 0;
$order_data['commission'] = 0;
}
// Marketing
$this->load->model('checkout/marketing');
$marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
if ($marketing_info) {
$order_data['marketing_id'] = $marketing_info['marketing_id'];
} else {
$order_data['marketing_id'] = 0;
}
} else {
$order_data['affiliate_id'] = 0;
$order_data['commission'] = 0;
$order_data['marketing_id'] = 0;
$order_data['tracking'] = '';
}
$order_data['language_id'] = $this->config->get('config_language_id');
$order_data['currency_id'] = $this->currency->getId();
$order_data['currency_code'] = $this->currency->getCode();
$order_data['currency_value'] = $this->currency->getValue($this->currency->getCode());
$order_data['ip'] = $this->request->server['REMOTE_ADDR'];
if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
$order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
} elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
$order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
} else {
$order_data['forwarded_ip'] = '';
}
if (isset($this->request->server['HTTP_USER_AGENT'])) {
$order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
} else {
$order_data['user_agent'] = '';
}
if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
$order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
} else {
$order_data['accept_language'] = '';
}
$this->load->model('checkout/order');
$this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
$data['text_recurring_item'] = $this->language->get('text_recurring_item');
$data['text_payment_recurring'] = $this->language->get('text_payment_recurring');
$data['column_name'] = $this->language->get('column_name');
$data['column_model'] = $this->language->get('column_model');
$data['column_quantity'] = $this->language->get('column_quantity');
$data['column_price'] = $this->language->get('column_price');
$data['column_total'] = $this->language->get('column_total');
$this->load->model('tool/upload');
$data['products'] = array();
foreach ($this->cart->getProducts() as $product) {
$option_data = array();
foreach ($product['option'] as $option) {
if ($option['type'] != 'file') {
$value = $option['value'];
} else {
$upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
if ($upload_info) {
$value = $upload_info['name'];
} else {
$value = '';
}
}
$option_data[] = array(
'name' => $option['name'],
'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
);
}
$recurring = '';
if ($product['recurring']) {
$frequencies = array(
'day' => $this->language->get('text_day'),
'week' => $this->language->get('text_week'),
'semi_month' => $this->language->get('text_semi_month'),
'month' => $this->language->get('text_month'),
'year' => $this->language->get('text_year'),
);
if ($product['recurring']['trial']) {
$recurring = sprintf($this->language->get('text_trial_description'), $this->currency->format($this->tax->calculate($product['recurring']['trial_price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax'))), $product['recurring']['trial_cycle'], $frequencies[$product['recurring']['trial_frequency']], $product['recurring']['trial_duration']) . ' ';
}
if ($product['recurring']['duration']) {
$recurring .= sprintf($this->language->get('text_payment_description'), $this->currency->format($this->tax->calculate($product['recurring']['price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax'))), $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']);
} else {
$recurring .= sprintf($this->language->get('text_payment_cancel'), $this->currency->format($this->tax->calculate($product['recurring']['price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax'))), $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']);
}
}
$data['products'][] = array(
'key' => $product['key'],
'product_id' => $product['product_id'],
'name' => $product['name'],
'model' => $product['model'],
'option' => $option_data,
'recurring' => $recurring,
'quantity' => $product['quantity'],
'subtract' => $product['subtract'],
'price' => $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'))),
'total' => $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')) * $product['quantity']),
'href' => $this->url->link('product/product', 'product_id=' . $product['product_id']),
);
}
// Gift Voucher
$data['vouchers'] = array();
if (!empty($this->session->data['vouchers'])) {
foreach ($this->session->data['vouchers'] as $voucher) {
$data['vouchers'][] = array(
'description' => $voucher['description'],
'amount' => $this->currency->format($voucher['amount'])
);
}
}
$data['totals'] = array();
foreach ($order_data['totals'] as $total) {
$data['totals'][] = array(
'title' => $total['title'],
'text' => $this->currency->format($total['value']),
);
}
//$data['payment'] = $this->load->controller('payment/' . $this->session->data['payment_method']['code']);
} else {
$data['redirect'] = $redirect;
}
echo json_encode("success");
}
Is this correct format or still any process to do like updating order table or etc...
I really don't know what to do next.. Please someone guide me to get rid of this issue..
Thanks

Opencart admin display order which orders have order status is > 0. Did you check your order_status_id in database it will be 0.
That's the issue. How Opencart works, when you are at checkout - confirm page but you haven't confirm your order, Opencart already entered one entry for that order with order status id - 0.
After that when you confirm your order than your selected payment method - callback function (in mostly payment method(s)) update your order status using model > checkout > order function addOrderHistory().
So problem is that you added your order to Opencart but not updated it's order_status_id so after adding order add a function to your module with will update order status of last (or your added) order. For that you can check default payment methods.

Related

Laravel Export to excel file not working for only five thousand data

I've been trying to create an export to excel file api in a production project.
But this api is working only for fewer data.
But when exporting for five thousand data, the excel file is downloaded after a long time with broken data in excel file.
Here is the code:
The route file-
Route::group(['prefix' => 'v1/export'], function () {
Route::get('/applied-candidate/{job_id}', 'Job\JobPostingUserController#exportAppliedCandidate');
});
In controller-
public function exportAppliedCandidate($jobposting_id)
{
$fileName = 'candidate_list_' . Carbon::now()->toDateString();
$exportable = new ExportableFromCollection(JobPostingUser::exportCandiateList($jobposting_id), JobPostingUser::listHeader());
return Excel::download($exportable, $fileName . '.xlsx');
}
In model-
public static function exportCandiateList($job_id): array {
$candidateList = JobPostingUser::where('posting_id', $job_id)
->join('users', 'users.id', '=' ,'job_posting_user.user_id')
->join('profile_basics', 'profile_basics.user_id', '=' ,'job_posting_user.user_id')
->join('job_postings', 'job_postings.id', '=' , 'job_posting_user.posting_id')
->select('job_postings.title as job_name',
'users.id as candidate_id',
'users.first_name',
'users.last_name',
'profile_basics.date_of_birth',
'profile_basics.gender',
'profile_basics.phone_personal',
'users.email',
'profile_basics.total_experience')->get()->toArray();
$final_result = [];
foreach($candidateList as $candidate) {
$bachelor = ProfileEducation::getBachelorInfo($candidate['candidate_id']);
$msc = ProfileEducation::getMasterInfo($candidate['candidate_id']);
$candidateInfo = [];
$job_name = JobPosting::where('id', $job_id)->first();
$job_name = $job_name ? $job_name->title: $job_id;
$candidateInfo['job'] = $job_name;
$candidateInfo['candidate_id'] = $candidate['candidate_id'];
$candidateInfo['name'] = $candidate['first_name'].' '.$candidate['last_name'];
$candidateInfo['date_of_birth'] = date('Y-m-d', strtotime($candidate['date_of_birth']));
$candidateInfo['gender'] = $candidate['gender'];
$candidateInfo['phone_personal'] = $candidate['phone_personal'];
$candidateInfo['email'] = $candidate['email'];
if($bachelor) {
$candidateInfo['b_university'] = empty($bachelor['institution']) ? $bachelor['other_institution'] : $bachelor['institution']['name'];
$candidateInfo['b_field'] = $bachelor['field'] ? ProfileService::getBachelorDegreeName($bachelor['field']): 'N/A';
$candidateInfo['b_major'] = $bachelor['major'] ? $bachelor['major']: 'N/A';
$candidateInfo['b_grade'] = $bachelor['grade'] ? $bachelor['grade']: 'N/A';
} else {
$candidateInfo['b_university'] = 'N/A';
$candidateInfo['b_field'] = '';
$candidateInfo['b_major'] = '';
$candidateInfo['b_grade'] = '';
}
if($msc) {
$candidateInfo['m_university'] = empty($msc['institution']) ? $msc['other_institution'] : $msc['institution']['name'];
$candidateInfo['m_field'] = $msc['field'] ? ProfileService::getMastersDegreeName($msc['field']): 'N/A';
$candidateInfo['m_major'] = $msc['major'] ? $msc['major']: 'N/A';
$candidateInfo['m_grade'] = $msc['grade'] ? $msc['grade']: 'N/A';
} else {
$candidateInfo['m_university'] = 'N/A';
$candidateInfo['m_field'] = '';
$candidateInfo['m_major'] = '';
$candidateInfo['m_grade'] = '';
}
$expericnece = self::getExperience($candidate['candidate_id']);
if($expericnece) {
$candidateInfo['company_name'] = $expericnece['company_name'];
$candidateInfo['started_in'] = $expericnece['started_in'];
$candidateInfo['ended_in'] = $expericnece['ended_in'];
$candidateInfo['responsibilitie'] = $expericnece['job_responsibilities'];
} else {
$candidateInfo['company_name'] = '';
$candidateInfo['started_in'] = '';
$candidateInfo['ended_in'] = '';
$candidateInfo['responsibilitie'] = '';
}
$candidateInfo['total_experience'] = $candidate['total_experience'];
$final_result[] = $candidateInfo;
}
return $final_result;
}
After exporting just few numbers are showing some columns in excel file. But file is correctly exported for lesser data(500 items).
Please suggest how I can change/optimise this query to work for any number of data?

Maatwebsite/Laravel-Excel View format

I am loading Laravel view and exporting as Excel using Maatwebsite/Laravel-Excel but my data showing as text but i need to make it as decimal, number. how can i do this. I have already read the documentation but there i cant find solution.
$fileName = 'Receipt Register : From '.date('d-m-Y', strtotime($date_from)).' To '.date('d-m-Y', strtotime($date_to)).($itemDetails ? ' For Item '.$itemDetails->item_code : "");
Excel::create($fileName, function( $excel) use($date_from, $date_to, $request) {
$excel->sheet('Receipt-Register', function($sheet) use($date_from, $date_to, $request) {
$itemDetails = [];
$itemFilterData = [];
$result = Ledger::where('receive_quantity', '!=', NULL)
->where('receive_quantity', ">", 0)
->orderBy('date', 'ASC')
->orderBy('mrn_number',"ASC")
->whereNotNull('mrn_number')
->whereNotNull('mrn_id')
->orderBy('id', "ASC")
->with('department', 'item', 'itemGroup', 'mrn')
->has('mrn', ">", 0);
if($request->date_from) {
$date_from = date('Y-m-d', strtotime($request->date_from));
$result = $result->whereDate('date', '>=', $date_from);
}
if($request->date_to) {
$date_to = date('Y-m-d', strtotime($request->date_to));
$result = $result->whereDate('date', '<=', $date_to);
}
if($request->item_id){
$result = $result->where('item_id', '=', $request->item_id);
$itemDetails = Item::find($request->item_id);
}
$results = $result->get();
$sheet->loadView('export_view',[
'results' => $results,
'date_from' => $date_from,
'date_to' => $date_to,
'itemFilterData' => $itemFilterData
]);
});
})->download('xlsx');

Batch bills- Submission Id

I need to grab the batch bill submission id (from different vendors) of the object from netsuite.Does anyone know how to do this?
TransactionSearchBasic transSearch = new TransactionSearchBasic();
SearchResult resVendorBill = service.search(transSearch);
resVendorBill.pageSize = 25;
resVendorBill.pageSizeSpecified = true;
resVendorBill.totalRecords = SearchRecentTransCount;
resVendorBill.totalRecordsSpecified = true;
transSearch.recordType = new SearchStringField() { #operator = SearchStringFieldOperator.#is, searchValue = "vendorpayment", operatorSpecified = true };
SearchResult resVendorPayment = service.search(transSearch);
if (resVendorPayment.status.isSuccess)
{
Record[] searchPaymentRecords = resVendorPayment.recordList;
if (searchPaymentRecords != null && searchPaymentRecords.Length >= 1)
{
List<VendorPayment> lstVendorPayments = searchPaymentRecords.Select(ep => (VendorPayment)ep).OrderByDescending(epo => epo.createdDate).Take(SearchRecentTransCount).ToList();
}
}

Drupal removing a node reference from a node

Ok, trying to process a script, both PHP and JavaScript, where I am moving a particular content type NODE from one reference to another. This is the structure:
I have a PROJECT
Inside each PROJECT are PAGES
Inside each PAGE are CALLOUTS
and Inside each CALLOUT are PRODUCTS.
What I want to do is take a PRODUCT from one CALLOUT to another CALLOUT. I am able to merge these, but now what I want to do is delete the first instance. An example:
I have PRODUCT AAG-794200 that is on PAGE 6 CALLOUT A. I am merging that PRODUCT with PAGE 6 CALLOUT B.
I can get the product to merge, but now I need to remove it from CALLOUT A. Here is my code:
$merge = explode(',', $merge); //Merge SKUs
$mpages = explode(',', $mpages); //Merge Pages
$mcallouts = explode(',', $mcallouts); //Merge Callouts
$mcallout_nid = explode(',', $mcallout_nid); //Merge Current callout
$length = count($merge);
$e = 0;
while ($e < $length) {
//Where is the SKU going to?
$to_callout_letter = strtoupper($mcallouts[$e]);
$to_page_num = $mpages[$e];
$sku = $merge[$e];
$from_callout = $mcallout_nid[$e];
//Where is the SKU coming from?
$other_callout = node_load($from_callout);
//Need page ID of current callout for project purposes
$page_nid = $other_callout->field_page[0]['nid'];
$page = node_load($page_nid);
//Need the project NID
$project_nid = $page->field_project[0]['nid'];
//We need to get the NID of the page we are going to
$page_nid = db_query('SELECT * FROM content_type_page WHERE field_page_order_value = "%d" and field_project_nid = "%d" ORDER BY vid DESC LIMIT 1', $to_page_num, $project_nid);
$page_nid_res = db_fetch_array($page_nid);
$to_page_nid = $page_nid_res['nid'];
//We need to get the NID of the callout here
$co_nid = db_query('SELECT * FROM content_type_callout WHERE field_identifier_value = "%s" and field_page_nid = "%d"', $to_callout_letter, $to_page_nid);
$co_nid_res = db_fetch_array($co_nid);
$to_callout_letter_nid = $co_nid_res['nid'];
//Load the present callout the SKU resides on
$f_callout = node_load($from_callout);
$callout = node_load($to_callout_letter_nid);
$long = count($f_callout->field_skus);
$deletecallout = array();
foreach($f_callout->field_skus as $skus) {
$s = 0;
while ($s < $long) {
if($skus['nid'] == $sku) {
$callout->field_skus[] = $skus;
$s++;
}
else {
$deletecallout[] = $skus;
$s++;
}
}
}
foreach($other_callout->field_images as $old_image) {
$callout->field_images[] = $old_image;
}
foreach($other_callout->field_line_art as $old_image) {
$callout->field_line_art[] = $old_image;
}
foreach($other_callout->field_swatches as $old_image) {
$callout->field_swatches[] = $old_image;
}
$callout->field_copy_text[0]['value'] .= $other_callout->field_copy_text[0]['value'];
$callout->field_notes[0]['value'] .= $other_callout->field_notes[0]['value'];
$callout->field_image_notes[0]['value'] .= $other_callout->field_image_notes[0]['value'];
$callout->field_status[0]['value'] = 'In Process';
node_save($callout);
This causes the PRODUCTS to MERGE, but not delete the original.
Thanks for any help. I know it's something simple, and it will be a palm-to-face moment.
I was actually able to solve this myself. #Chris - The brace ended after node_save(callout); I must have missed that when I copied and pasted. However, here is the code I ended up using:
$merge = explode(',', $merge); //Merge SKUs
$mpages = explode(',', $mpages); //Merge Pages
$mcallouts = explode(',', $mcallouts); //Merge Callouts
$mcallout_nid = explode(',', $mcallout_nid); //Merge Current callout
if($merge[0] !== '0') {
//Store NIDs of Old Callouts to the proper SKU
$oc_sku = array();
$oc_sku_e = count($merge);
$oc_sku_ee = 0;
while ($oc_sku_ee < $oc_sku_e) {
$curr_sku = $merge[$oc_sku_ee];
$curr_oldco = $mcallout_nid[$oc_sku_ee];
$oc_sku[$curr_sku] = $curr_oldco;
$oc_sku_ee++;
}
//Convert page numbers to page_nids
$pc = count($mpages); //How many pages are we getting
$pc_e = 0;
while($pc_e < $pc) {
$nid = $mpages[$pc_e];
$sql = db_query('SELECT * FROM content_type_page WHERE field_page_order_value = "%d" AND field_project_nid = "%d" ORDER BY vid DESC LIMIT 1', $nid, $project_nid);
$res = db_fetch_array($sql);
if($res) {
$npage_arr[] = $res['nid'];
} else { //If there is no page, we need to create it here.
$node = new StdClass();
$node->type = 'page';
$node->title = 'Page ' . $nid . ' of ' . $project->title;
$node->field_project[0]['nid'] = $project_nid;
$node->field_page_order[0]['value'] = $nid;
$node = node_submit($node);
node_save($node);
$npage_arr[] = $node->nid;
}
$pc_e++;
}
// Convert callout letters to callout_nids
$coc = count($mcallouts);
$coc_e = 0;
while($coc_e < $coc) {
$cnid = strtoupper($mcallouts[$coc_e]);
$pnid = $npage_arr[$coc_e];
$page_node = node_load($pnid);
$sql = db_query('SELECT * FROM content_type_callout WHERE field_identifier_value = "%s" AND field_page_nid = "%d" ORDER BY vid DESC LIMIT 1', $cnid, $pnid);
$res = db_fetch_array($sql);
if($res) {
$cpage_arr[] = $res['nid'];
} else { //If there is no callout that exists, we need to make it here.
$callout_node = new stdClass();
$callout_node->type = 'callout';
$callout_node->field_page[0]['nid'] = $pnid;
$callout_node->field_identifier[0]['value'] = $cnid;
$callout_node->field_sequence[0]['value'] = 0;
$callout_node->title = "Callout ".$callout." on page ".$page_node->field_page_order[0]['value'];
$callout_node->field_project[0]['nid'] = $project->nid;
$callout_node->field_wholesaler[0]['value'] = $project->field_wholesaler[0]['value'];
$callout_node->field_skus = array();
$callout_node->status = 1;
$callout_node->uid = 1;
$callout_node->revision = true;
$callout_node = node_submit($callout_node);
node_save($callout_node);
$cpage_arr[] = $callout_node->nid;
}
$coc_e++;
}
//Now we need to assign the skus to the appropriate callout for processing
$coc2 = count($cpage_arr);
$coc_e2 = 0;
while($coc_e2 < $coc2) {
$co = $cpage_arr[$coc_e2];
if($co !== '0') {
$sku = $merge[$coc_e2];
$m_arr[$co][] = $sku;
}
$coc_e2++;
}
//we need a way to centrally store all NID's of SKUs to the callouts they belong to
$oc_arr = array();
$oc = count($mcallout_nid);
$oc_e = 0;
while($oc_e < $oc) {
$f_callout = $mcallout_nid[$oc_e];
$former_callout = node_load($f_callout);
foreach($former_callout->field_skus as $key=>$skus) {
$oc_arr[] = $skus;
}
$oc_e++;
}
//Now we are processing the Pages/Callouts/SKUs to save
$pc_e2 = 0;
foreach($m_arr as $key=>$values) {
$callout = node_load($key);
foreach($values as $value) {
$oc = count($oc_arr);
$oc_e = 0;
while($oc_e < $oc) {
$skus = $oc_arr[$oc_e];
if($value == $skus['nid']) {
$callout->field_skus[] = $skus;
//$nid = $oc_sku[$value];
$old_callout_info[] = $oc_sku[$value];
$oc_e = $oc;
}
else {
$oc_e++;
}
}
}
foreach($old_callout_info as $nid) {
/* $nid = $oc_sku[$value]; */
$former_callout = node_load($nid);
foreach($former_callout->field_images as $old_image) {
$callout->field_images[] = $old_image;
}
foreach($former_callout->field_line_art as $old_image) {
$callout->field_line_art[] = $old_image;
}
foreach($former_callout->field_swatches as $old_image) {
$callout->field_swatches[] = $old_image;
}
$callout->field_copy_text[0]['value'] .= $former_callout->field_copy_text[0]['value'];
}
$callout->field_notes[0]['value'] .= $former_callout->field_notes[0]['value'];
$callout->field_image_notes[0]['value'] .= $former_callout->field_image_notes[0]['value'];
$callout->field_logos = $former_callout->field_logos;
$callout->field_affiliations = $former_callout->field_affiliations;
$callout->field_graphics = $former_callout->field_graphics;
$callout->revision = 1;
$callout->field_status[0]['value'] = 'inprocess';
node_save($callout);
$pc_e2++;
}
}
I realize this can probably be simplified in a way, but as for now, this works perfectly considering what I'm trying to do. No complaints from the client so far. Thanks for taking a look Drupal Community.

How to retrieve all the reviews publicly available for an extension in the Google Chrome webstore - JSON & cross-domain issue

I'm interested in gathering/scraping data about the reviews earned by popular extensions available in the Chrome Webstore.
In particular, I need to retrieve the number of total reviews left for a specific extension and then retrieve all the reviews publicly available for this addon. My problem is the following: I cannot write a standard PHP Curl scraper since the data I'm interested in is available through json requests, in particular, I need to call:
https://chrome.google.com/reviews/components for the number of
reviews ('numRatings')
https://chrome.google.com/reviews/json/search
for the reviews ("comment")
I tried to write this:
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
function getReviews(extensionId, callback) {
var entities = [{'url' : 'http://chrome.google.com/extensions/permalink?id=' + extensionId}];
var param = {"searchSpecs":[{"requireComment":true,"entities": entities,"groups":["public_comment"],"matchExtraGroups":true,"sortBy":"quality","startIndex":10,"numResults":10,"includeNickNames":true}],"applicationId":94};
$.ajax({
type: 'POST',
url: 'https://chrome.google.com/reviews/json/search',
contentType: 'application/xml',
xhrFields: {withCredentials: true },
dataType: 'json',
data: 'req=' + JSON.stringify(param) + '&requestSource=widget'
}).success(callback);
}
</script>
<script type="text/javascript">
$(document).ready(getReviews('gighmmpiobklfepjocnamgkkbiglidom', function(reviews) { console.log(reviews); }));
</script>
I'm not very keen in jQuery/JSON(-P) and the code above is certainly wrong.
My questions are as follows:
How to bypass the same-domain policy? I tried YQL without success...
How to format my url/'data' to only retrieve the number of
reviews ('numRatings') on chrome.google.com/reviews/components and the reviews ('comments') on chrome.google.com/reviews/json/search for a specific extension identified by its id, e.g. gighmmpiobklfepjocnamgkkbiglidom?
I already accomplished this kind of scraping for popular Mozilla Addons using PHP and gathered the data I needed using a standard curl/XPath.
Thanks for your help!
1) The easiest way would be to create a Chrome extension;
2) See https://github.com/xpressyoo/MyExtensions
[...]
getComments : function() {
var entities = [];
//each(Ext.extensions, function(data, id) {
entities.push({'url' : 'http://chrome.google.com/extensions/permalink?id=' + this.hash});
//});
Ext.XHR['comments'] = new Ajax({
'method' : 'POST',
'encodeURI' : false, // Needed
'url' : 'https://chrome.google.com/reviews/json/search',
'headers' : {
'Content-type' : 'application/xml'
},
'parameters' : {
'req' : JSON.stringify({'searchSpecs' : [{'entities' : entities, 'groups' : ['public_comment'], 'matchExtraGroups' : true,"sortBy":"quality", 'startIndex' : 0, 'numResults' : 80, 'includeNickNames' : true}], 'applicationId' : 94 }) + '&requestSource=widget'
},
'onSuccess' : function(xhr) {
var json = xhr.responseJSON;
if(json && json.searchResults ) {
this.comments = {
'total' : Number(json.searchResults[0].numAnnotations.toString().replace(/,/, '').toInt()),
'latest' : json.searchResults[0].annotations ? json.searchResults[0].annotations[0] :{},
'previous' : this.comments.total || null,
'latestPrevious' : $merge(this.comments.latest) || null,
'new' : this.comments['new'] || false
}
Ext.XHR['comments'] = null;
}
}.bind(this)
}).send();
return this;
},
[...]
and
var nbreviews = this.comments.total; //The number of reviews
var latestcomment = (this.comments.latest0 && this.comments.latest0.comment ? this.comments.latest0.comment.replace(/\n/gi, '') : '');// get the latest comment
var nthcomment = (this.comments.latestn && this.comments.latestn.comment ? this.comments.latestn.comment.replace(/\n/gi, '') : '');//Get the nth comment
where:
'latestn' : json.searchResults[0].annotations ? json.searchResults[0].annotations[n] :{},
Here is a way of doing it in PHP with parallel cURL. This script scrapes all the extensions present in the Chrome webstore (ranked by popularity) and retrieves information such as:
Number of users
Number of star-ratings
Number of text reviews
Number of characters for each text-review (max 100 reviews scraped for each extension)
//GET URL
$url0 = "https://chrome.google.com/";
//AUTO LOOP
foreach(range(0, 705, 5) as $x) {
//Nb PAGES TO DOWNLOAD
$frompge = $x+1;
$topge = $x+5;
$nbpages = ($topge - $frompge)+1;
$zitems = $nbpages*20;
//MULTI cURL INIT
$mh = curl_multi_init();
$running = null;
//GENERATE URLs ARRAY
$urls = array();
for ($a = $frompge; $a <= $topge; $a++){
$aa = $url0 . 'webstore/list/most_popular/'. $a .'?category=ext';
$urls[] = $aa;
}
foreach ($urls as $name => $url)
{
$c[$name]=curl_init($url);
curl_setopt($c[$name], CURLOPT_HEADER, false);
curl_setopt($c[$name], CURLOPT_FAILONERROR, true);
curl_setopt($c[$name], CURLOPT_FOLLOWLOCATION, true);
curl_setopt($c[$name], CURLOPT_AUTOREFERER, true);
curl_setopt($c[$name], CURLOPT_RETURNTRANSFER, true);
curl_setopt($c[$name], CURLOPT_TIMEOUT, 10);
curl_multi_add_handle ($mh,$c[$name]);
}
// execute all queries simultaneously, and continue when all are complete
do {
curl_multi_exec($mh, $running);
} while ($running >0);
$html = array();
foreach ($urls as $name => $url)
{
$html[]=curl_multi_getcontent($c[$name]);
curl_multi_remove_handle($mh,$c[$name]);
curl_close($c[$name]);
}
curl_multi_close($mh);
for ($b = 0; $b <= $nbpages-1; $b++) {
// Parse the HTML information and return the results.
$dom = new DOMDocument();
#$dom->loadHtml($html[$b]);
$xpath = new DOMXPath($dom);
$links = $xpath->query("//a[contains(#class, 'title-a')]");
$result = array();
foreach ( $links as $item ) {
$newDom = new DOMDocument;
$newDom->appendChild($newDom->importNode($item,true));
$xpath = new DOMXPath( $newDom );
$cleaner = array(" users", " user", "(", ")", ","," ");
$data = str_replace($cleaner,"",trim($xpath->query("//script")->item(0)->nodeValue));
list($b1,$id,$b2,$b3,$b4,$name,$b5,$b6,$b7,$b8,$b9,$b10,$b11,$b12,$b13,$nbusers) = explode("\"", $data);
$label = str_replace(" ", "", strtolower(ereg_replace("[^A-Za-z0-9 ]", "", $name)));
//CATEGORIES (based on nb of users)
if($nbusers<100){$category = '1';$color = 'inherit';}
else if($nbusers>=100 && $nbusers<1000){$category = '2';$color = '#E6EEEE';}
else if($nbusers>=1000 && $nbusers<10000){$category = '3';$color = '#CDDEDE';}
else if($nbusers>=10000 && $nbusers<100000){$category = '4';$color = '#B5CDCD';}
else if($nbusers>=100000 && $nbusers<1000000){$category = '5';$color = '#9CBDBD';}
else if($nbusers == '1000000+'){$category = '6';$color = '#83ACAC';}
else{$category = '-9';}
/////////////////////////////////////////////LOOP REVIEWS
$extURL = 'http://chrome.google.com/extensions/permalink?id='.$id;
$c1 = curl_init('https://chrome.google.com/reviews/json/search');
$c1a = curl_init('https://chrome.google.com/reviews/json/search');
$c2 = curl_init('https://chrome.google.com/reviews/json/lookup');
$fields1 = http_build_query(array(
'req' => '{"searchSpecs":[{"requireComment":true,"entities":[{"url":"'.$extURL.'"}],"groups":["public_comment"],"matchExtraGroups":true,"sortBy":"quality","startIndex":0,"numResults":100,"includeNickNames":false}],"applicationId":94}',
));
$options1 = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_POSTFIELDS => $fields1,
);
$fields1a = http_build_query(array(
'req' => '{"searchSpecs":[{"requireComment":true,"entities":[{"url":"'.$extURL.'"}],"groups":["public_comment"],"matchExtraGroups":true,"startIndex":0,"numResults":100,"includeNickNames":false}],"applicationId":94}',
));
$options1a = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_POSTFIELDS => $fields1a,
);
$fields2 = http_build_query(array(
'req' => '{"entities":[{"url" : "'.$extURL.'", "includeAggregateInfo" : true}],"applicationId":94}',
));
$options2 = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_POSTFIELDS => $fields2,
);
curl_setopt_array($c1, $options1);
curl_setopt_array($c1a, $options1a);
curl_setopt_array($c2, $options2);
$mh2 = curl_multi_init();
curl_multi_add_handle($mh2,$c1);
curl_multi_add_handle($mh2,$c1a);
curl_multi_add_handle($mh2,$c2);
$active = null;
do {
curl_multi_exec($mh2, $active);
} while ($active >0);
//close the handles$c1 = curl_init('https://chrome.google.com/reviews/json/search');
$json1=curl_multi_getcontent($c1);
$json1a=curl_multi_getcontent($c1a);
$json2=curl_multi_getcontent($c2);
curl_multi_remove_handle($mh2, $c1);
curl_multi_remove_handle($mh2, $c1a);
curl_multi_remove_handle($mh2, $c2);
curl_multi_close($mh2);
$data1 = json_decode(utf8_encode($json1), true);
$data1a = json_decode(utf8_encode($json1a), true);
$data2 = json_decode(utf8_encode($json2), true);
if ($data1['channelHeader']['errorCode']) return;
$nbreviews = $data1['searchResults'][0]['numAnnotations'];
if ($nbreviews > 100){$nbreviews2=100;}
else{$nbreviews2=$nbreviews;}
//Sum strings
$comments = $data1['searchResults'][0]['annotations'];
$sum =0;
foreach($comments as $comment){
$msg = preg_replace('/[\n\r\t]/', ' ', htmlspecialchars($comment['comment']));
$msg = str_replace(">", "", $msg);
$msg = str_replace(" ", "", $msg);
$strlen = strlen($msg);
$sum += $strlen;
}
$add = $sum;
$final = $add/$nbreviews2;
//Sum strings A
if ($data1a['channelHeader']['errorCode']) return;
$nbreviewsa = $data1a['searchResults'][0]['numAnnotations'];
$commentsa = $data1a['searchResults'][0]['annotations'];
$suma =0;
foreach($commentsa as $commenta){
$msga = preg_replace('/[\n\r\t]/', ' ', htmlspecialchars($commenta['comment']));
$msga = str_replace(">", "", $msga);
$msga = str_replace(" ", "", $msga);
$strlena = strlen($msga);
$suma += $strlena;
}
$adda = $suma;
$finala = $adda/$nbreviews2;
//Ratings
if ($data2['channelHeader']['errorCode']) return;
$nbratings = $data2['annotations'][0]['aggregateInfo']['numRatings'];
$nbstars = $data2['annotations'][0]['aggregateInfo']['averageRating'];
$delta = $nbratings - $nbreviews;
$ratio = $nbratings/$nbusers;
$ratio2 = $nbreviews/$nbusers;
////////////////////////////////////////////END LOOP REVIEWS
//PUT VALUES TOGETHER
$result[] = array($name,$label,$id,$category,$nbusers,$nbratings,$nbreviews,$nbreviewsa,$delta,$ratio,$ratio2,$nbstars,$nbreviews2,$add,$final,$adda,$finala);
}//END FOREACH
//print_r($result,false);
//DISPLAY RESULTS
for ($z = 0; $z <= 20; $z++) {
echo "<tr><td class=\"non\">" .$result[$z][0] . "</td><td class=\"non\">" .$result[$z][1] . "</td><td>" .$result[$z][3] . "</td><td>" .$result[$z][4] . "</td><td>" .$result[$z][5] . "</td><td>" .$result[$z][6] . "</td><td>" .$result[$z][7] . "</td><td>" .$result[$z][8] . "</td><td>" .$result[$z][9] . "</td><td>" .$result[$z][10] . "</td><td>" .$result[$z][11] . "</td><td>" .$result[$z][12] . "</td><td>" .$result[$z][13] . "</td><td>" .$result[$z][14] . "</td><td>" .$result[$z][15] . "</td><td>" .$result[$z][16] . "</td></tr>";
ob_flush();
flush();
}
}
}//END FOREACH

Resources