Using $this when not in object context - MyBB - php

So, I'm using MyBB forums, and I go to moderate a thread, and get this error.
Fatal error: Using $this when not in object context in C:\zpanel\hostdata\sdcore\public_html\forums\inc\class_moderation.php on line 642
the code on line 642 is
$this->delete_thread($mergetid);
And the surrounding code (just in case)
$db->delete_query("threadsubscriptions", "tid = '{$mergetid}'");
update_first_post($tid);
$arguments = array("mergetid" => $mergetid, "tid" => $tid, "subject" => $subject);
$plugins->run_hooks("class_moderation_merge_threads", $arguments);
$this->delete_thread($mergetid);
and the delete thread function
function delete_thread($tid)
{
global $db, $cache, $plugins;
$tid = intval($tid);
$plugins->run_hooks("class_moderation_delete_thread_start", $tid);
$thread = get_thread($tid);
$userposts = array();
// Find the pid, uid, visibility, and forum post count status
$query = $db->query("
SELECT p.pid, p.uid, p.visible, f.usepostcounts
FROM ".TABLE_PREFIX."posts p
LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid)
WHERE p.tid='{$tid}'
");
$pids = array();
$num_unapproved_posts = $num_approved_posts = 0;
while($post = $db->fetch_array($query))
{
$pids[] = $post['pid'];
$usepostcounts = $post['usepostcounts'];
if(!function_exists("remove_attachments"))
{
require MYBB_ROOT."inc/functions_upload.php";
}
// Remove attachments
remove_attachments($post['pid']);
// If the post is unapproved, count it!
if($post['visible'] == 0 || $thread['visible'] == 0)
{
$num_unapproved_posts++;
}
else
{
$num_approved_posts++;
// Count the post counts for each user to be subtracted
++$userposts[$post['uid']];
}
}
// Remove post count from users
if($usepostcounts != 0)
{
if(is_array($userposts))
{
foreach($userposts as $uid => $subtract)
{
$db->update_query("users", array('postnum' => "postnum-{$subtract}"), "uid='".intval($uid)."'", 1, true);
}
}
}
// Delete posts and their attachments
if($pids)
{
$pids = implode(',', $pids);
$db->delete_query("posts", "pid IN ($pids)");
$db->delete_query("attachments", "pid IN ($pids)");
$db->delete_query("reportedposts", "pid IN ($pids)");
}
// Implied counters for unapproved thread
if($thread['visible'] == 0)
{
$num_unapproved_posts += $num_approved_posts;
}
// Delete threads, redirects, subscriptions, polls, and poll votes
$db->delete_query("threads", "tid='$tid'");
$db->delete_query("threads", "closed='moved|$tid'");
$db->delete_query("threadsubscriptions", "tid='$tid'");
$db->delete_query("polls", "tid='$tid'");
$db->delete_query("pollvotes", "pid='".$thread['poll']."'");
$db->delete_query("threadsread", "tid='$tid'");
$db->delete_query("threadratings", "tid='$tid'");
$updated_counters = array(
"posts" => "-{$num_approved_posts}",
"unapprovedposts" => "-{$num_unapproved_posts}"
);
if($thread['visible'] == 1)
{
$updated_counters['threads'] = -1;
}
else
{
$updated_counters['unapprovedthreads'] = -1;
}
if(substr($thread['closed'], 0, 5) != "moved")
{
// Update forum count
update_forum_counters($thread['fid'], $updated_counters);
}
$plugins->run_hooks("class_moderation_delete_thread", $tid);
return true;
}
How would I go about fixing this?

Related

Sphinx Query is returning null results in PHP

I am currently using PHP to query from my sphinx index. The index is building properly, however the search is not.
Originally I had my query set up like the following:
private function _doMapSearchAll($textSearch, $typeFilterArr, $rads = array(), $centre = array(), $showFavourites = false) {
// lookup the location based on the search and return the results in that
// map bounds ignore for boundary searches
$rsArr = array();
$skipDataSearch = false;
if (!COUNT($rads)) {
// handle airport code lookups if we have 3 characters
if (strlen($textSearch) === 3) {
$rsArr = $this->_doMapAirportSearch($textSearch);
if (COUNT($rsArr)) {
$skipDataSearch = true;
}
}
// still no results based on the above search, do generic map search
if ($skipDataSearch === false) {
$rsArr = $this->_doMapGeoSearch($textSearch, $typeFilterArr, $centre);
if (COUNT($rsArr['results']) > 0) {
$skipDataSearch = false;
}
}
}
// if we are doing a boundary search, or we have no results from the above,
// get all results based on our location
if ($skipDataSearch === false) {
// fall back onto searching via the data
// normalise the search string
$originalSearchString = $this->doNormalisation($textSearch);
// use sphinx for the search
$sphinx = $this->_getSphinxConnection();
$sphinx->setLimits(0, $this->container->getParameter('search_max_results'), $this->container->getParameter('search_max_results'));
if (COUNT($typeFilterArr)) {
$sphinx->SetFilter('fldSiteTypeUID_attr', $typeFilterArr);
}
// if we're doing a boundary search, skip the search string
if (COUNT($rads) > 0) {
$originalSearchString = '';
if ($showFavourites === false) {
//$sphinx->SetFilterFloatRange('lat_radians', min($rads['minLat'], $rads['maxLat']), max($rads['minLat'], $rads['maxLat']));
//$sphinx->SetFilterFloatRange('long_radians', min($rads['minLon'], $rads['maxLon']), max($rads['minLon'], $rads['maxLon']));
if ($rads['minLat'] > $rads['maxLat']) {
$rads['minLat'] = $rads['minLat'] - 360;
}
if ($rads['minLon'] > $rads['maxLon']) {
$rads['minLon'] = $rads['minLon'] - 180;
}
$sphinx->SetFilterFloatRange('lat_radians', $rads['minLat'], $rads['maxLat']);
$sphinx->SetFilterFloatRange('long_radians', $rads['minLon'], $rads['maxLon']);
}
}
// order by centre point
if (COUNT($centre) > 0) {
// otherwise start in the centre
$sphinx->SetGeoAnchor('lat_radians', 'long_radians', (float) $centre['centreLat'], (float) $centre['centreLon']);
$lintDistanceLimit = 999999999.0; // everything
if ($showFavourites === false && isset($rads['maxLat'])) {
$radiusMiles = $this->get('geolocation_helper')->getSeparation(
rad2deg($rads['maxLat']),
rad2deg($rads['minLon']),
rad2deg($rads['minLat']),
rad2deg($rads['maxLon']),
"M"
);
$lintDistanceLimit = $radiusMiles * 1609; // miles to meters...
}
$sphinx->SetFilterFloatRange('geodist', 0.0, (float)$lintDistanceLimit);
$sphinx->SetSortMode(SPH_SORT_EXTENDED, 'geodist ASC');
} else {
// apply search weights
$sphinx->SetFieldWeights(array('fldTown_str' => 100, 'fldAddress1_str' => 30, 'fldSiteName_str' => 20));
}
// if we should be limiting to only favourites, pickup the selected
// favourites from cookies
if ($showFavourites === true) {
$request = $this->container->get('request_stack')->getCurrentRequest();
$favourites = explode(',', $request->cookies->get('HSF_favlist'));
if (count($favourites)) {
foreach ($favourites as $k => $favourite) {
$favourites[$k] = (int)$favourite;
}
$sphinx->SetFilter('fldUID_attr', $favourites);
}
}
$rs = $sphinx->Query($originalSearchString, $this->container->getParameter('sphinx_index'));
echo json_encode($sphinx);
$rsArr['results'] = array();
if (isset($rs['matches']) && count($rs['matches'])) {
// update the search text to what we actually searched for, this
// is needed in case we've updated/set $rsArr['searchText']
// after a geolookup
$rsArr['searchText'] = $textSearch;
// clear any previous bounds set by the geolookup, we don't want this
// if we have direct text match results
$rsArr['geobounds'] = array();
if (isset($rs['matches']) && count($rs['matches'])) {
foreach ($rs['matches'] as $k => $match) {
$rsArr['results'][$k] = $this->_remapSphinxData($k, $match);
}
}
// sort the results by distance
usort($rsArr['results'], function ($a, $b) {
return $a['fldDistance'] - $b['fldDistance'];
});
}
}
// add on the total record count
$rsArr['total'] = (int) COUNT($rsArr['results']);
return $rsArr;
}
That was returning nothing and giving me the error for GEODIST():
{"_host":"sphinx","_port":36307,"_path":"","_socket":false,"_offset":0,"_limit":250,"_mode":0,"_weights":[],"_sort":4,"_sortby":"geodist ASC","_min_id":0,"_max_id":0,"_filters":[{"type":2,"attr":"geodist","exclude":false,"min":0,"max":999999999}],"_groupby":"","_groupfunc":0,"_groupsort":"#group desc","_groupdistinct":"","_maxmatches":"250","_cutoff":0,"_retrycount":0,"_retrydelay":0,"_anchor":{"attrlat":"lat_radians","attrlong":"long_radians","lat":0.9300859583877783,"long":-2.0943951023931953},"_indexweights":[],"_ranker":0,"_rankexpr":"","_maxquerytime":0,"_fieldweights":[],"_overrides":[],"_select":"*","_error":"searchd error: geoanchor is deprecated (and slow); use GEODIST() expression","_warning":"","_connerror":false,"_reqs":[],"_mbenc":"","_arrayresult":false,"_timeout":0}{"results":[],"bounds":{"bllat":53.395603,"trlat":53.7159857,"bllng":-113.7138017,"trlng":-113.2716433},"geocentre":{"lat":53.5461245,"lon":-113.4938229},"checksum":"204a43923452936b00a10c8e566c4a48d4fdb280f97fd4042646eb45c8257bbc","searchText":"Edmonton, AB, Canada","skipResults":true,"showFavourites":false}
To fix this I changed the SetGeoAnchor function to the following:
private function _doMapSearchAll($textSearch, $typeFilterArr, $rads = array(), $centre = array(), $showFavourites = false) {
// lookup the location based on the search and return the results in that
// map bounds ignore for boundary searches
$rsArr = array();
$skipDataSearch = false;
if (!COUNT($rads)) {
// handle airport code lookups if we have 3 characters
if (strlen($textSearch) === 3) {
$rsArr = $this->_doMapAirportSearch($textSearch);
if (COUNT($rsArr)) {
$skipDataSearch = true;
}
}
// still no results based on the above search, do generic map search
if ($skipDataSearch === false) {
$rsArr = $this->_doMapGeoSearch($textSearch, $typeFilterArr, $centre);
if (COUNT($rsArr['results']) > 0) {
$skipDataSearch = false;
}
}
}
// if we are doing a boundary search, or we have no results from the above,
// get all results based on our location
if ($skipDataSearch === false) {
// fall back onto searching via the data
// normalise the search string
$originalSearchString = $this->doNormalisation($textSearch);
// use sphinx for the search
$sphinx = $this->_getSphinxConnection();
$sphinx->setLimits(0, $this->container->getParameter('search_max_results'), $this->container->getParameter('search_max_results'));
if (COUNT($typeFilterArr)) {
$sphinx->SetFilter('fldSiteTypeUID_attr', $typeFilterArr);
}
// if we're doing a boundary search, skip the search string
if (COUNT($rads) > 0) {
$originalSearchString = '';
if ($showFavourites === false) {
//$sphinx->SetFilterFloatRange('lat_radians', min($rads['minLat'], $rads['maxLat']), max($rads['minLat'], $rads['maxLat']));
//$sphinx->SetFilterFloatRange('long_radians', min($rads['minLon'], $rads['maxLon']), max($rads['minLon'], $rads['maxLon']));
if ($rads['minLat'] > $rads['maxLat']) {
$rads['minLat'] = $rads['minLat'] - 360;
}
if ($rads['minLon'] > $rads['maxLon']) {
$rads['minLon'] = $rads['minLon'] - 180;
}
$sphinx->SetFilterFloatRange('lat_radians', $rads['minLat'], $rads['maxLat']);
$sphinx->SetFilterFloatRange('long_radians', $rads['minLon'], $rads['maxLon']);
}
}
// order by centre point
if (COUNT($centre) > 0) {
// otherwise start in the centre
// $sphinx->SetGeoAnchor('lat_radians', 'long_radians', (float) $centre['centreLat'], (float) $centre['centreLon']);
$centreLat = (float) $centre['centreLat'];
$centreLon = (float) $centre['centreLon'];
$sphinx->SetSelect("GEODIST(lat_radians, long_radians, $centreLat, $centreLon) AS geodist");
$lintDistanceLimit = 999999999.0; // everything
if ($showFavourites === false && isset($rads['maxLat'])) {
$radiusMiles = $this->get('geolocation_helper')->getSeparation(
rad2deg($rads['maxLat']),
rad2deg($rads['minLon']),
rad2deg($rads['minLat']),
rad2deg($rads['maxLon']),
"M"
);
$lintDistanceLimit = $radiusMiles * 1609; // miles to meters...
}
$sphinx->SetFilterFloatRange('geodist', 0.0, (float)$lintDistanceLimit);
$sphinx->SetSortMode(SPH_SORT_EXTENDED, 'geodist ASC');
} else {
// apply search weights
$sphinx->SetFieldWeights(array('fldTown_str' => 100, 'fldAddress1_str' => 30, 'fldSiteName_str' => 20));
}
// if we should be limiting to only favourites, pickup the selected
// favourites from cookies
if ($showFavourites === true) {
$request = $this->container->get('request_stack')->getCurrentRequest();
$favourites = explode(',', $request->cookies->get('HSF_favlist'));
if (count($favourites)) {
foreach ($favourites as $k => $favourite) {
$favourites[$k] = (int)$favourite;
}
$sphinx->SetFilter('fldUID_attr', $favourites);
}
}
$rs = $sphinx->Query($originalSearchString, $this->container->getParameter('sphinx_index'));
echo json_encode($sphinx);
$rsArr['results'] = array();
if (isset($rs['matches']) && count($rs['matches'])) {
// update the search text to what we actually searched for, this
// is needed in case we've updated/set $rsArr['searchText']
// after a geolookup
$rsArr['searchText'] = $textSearch;
// clear any previous bounds set by the geolookup, we don't want this
// if we have direct text match results
$rsArr['geobounds'] = array();
if (isset($rs['matches']) && count($rs['matches'])) {
foreach ($rs['matches'] as $k => $match) {
$rsArr['results'][$k] = $this->_remapSphinxData($k, $match);
}
}
// sort the results by distance
usort($rsArr['results'], function ($a, $b) {
return $a['fldDistance'] - $b['fldDistance'];
});
}
}
// add on the total record count
$rsArr['total'] = (int) COUNT($rsArr['results']);
return $rsArr;
}
This gives me back results however they look like this:
{"_host":"sphinx","_port":36307,"_path":"","_socket":false,"_offset":0,"_limit":250,"_mode":0,"_weights":[],"_sort":4,"_sortby":"geodist ASC","_min_id":0,"_max_id":0,"_filters":[{"type":2,"attr":"geodist","exclude":false,"min":0,"max":999999999}],"_groupby":"","_groupfunc":0,"_groupsort":"#group desc","_groupdistinct":"","_maxmatches":"250","_cutoff":0,"_retrycount":0,"_retrydelay":0,"_anchor":[],"_indexweights":[],"_ranker":0,"_rankexpr":"","_maxquerytime":0,"_fieldweights":[],"_overrides":[],"_select":"GEODIST(lat_radians, long_radians, 0.93008595838778, -2.0943951023932) AS geodist","_error":"","_warning":"","_connerror":false,"_reqs":[],"_mbenc":"","_arrayresult":false,"_timeout":0}{"results":[[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,34362776,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,38279990,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7963188,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7971966,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31790051,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7972301,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,33589292,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,33589642,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7962913,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31789941,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,7962178,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,49484181,null,""],[null,null,null,null,null,null,null,"Other","http:\/\/localhost:8080\/themes\/docker\/images\/Site-Type-Other.png",null,31795436,null,""],
.....
My searchd config looks like this:
searchd
{
listen = 36307
listen = 9306:mysql41
log = /opt/sphinx/searchd.log
query_log = /opt/sphinx/query.log
read_timeout = 5
max_children = 30
pid_file = /opt/sphinx/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
binlog_path = /opt/sphinx/
}
I am new tp Sphinx and need help correcting this query. Any thoughts?
Edit: This is sphinx version 3.4.1
So after hours on this over the past few days, I have found the answer...:
I was missing the * in the statement:
$sphinx->SetSelect("*, GEODIST($centreLat, $centreLon, lat_radians, long_radians) as geodist");
I hope this helps anyone who has this issue in the future

add function in php file get Call to undefined function exception

I'm new on php, I'm triyng to backup a post before deleting on a mybb forum.
I edited inc/class_moderation.php adding the following function backup_post, but when the call to the function backup_post
throws
Call to undefined function backup_post() in
/membri/myforum/inc/class_moderation.php on line 485
function delete_post($pid)
{
global $mybb, $db, $cache, $plugins;
$pid = $plugins->run_hooks("class_moderation_delete_post_start", $pid);
// Get pid, uid, fid, tid, visibility, forum post count status of post
$pid = intval($pid);
$query = $db->query("
SELECT p.pid, p.uid, p.fid, p.tid, p.visible, f.usepostcounts, t.visible as threadvisible, message, p.username as p_username, p.subject, p.dateline
FROM ".TABLE_PREFIX."posts p
LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid)
LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid)
WHERE p.pid='$pid'
");
$post = $db->fetch_array($query);
// If post counts enabled in this forum and it hasn't already been unapproved, remove 1
if($post['usepostcounts'] != 0 && $post['visible'] != 0 && $post['threadvisible'] != 0)
{
$db->update_query("users", array("postnum" => "postnum-1"), "uid='{$post['uid']}'", 1, true);
}
if(!function_exists("remove_attachments"))
{
require MYBB_ROOT."inc/functions_upload.php";
}
// Remove attachments
remove_attachments($pid);
//Backup the post
backup_post($pid);
// Delete the post
$db->delete_query("posts", "pid='$pid'");
// Remove any reports attached to this post
$db->delete_query("reportedposts", "pid='$pid'");
$num_unapproved_posts = $num_approved_posts = 0;
// Update unapproved post count
if($post['visible'] == 0 || $post['threadvisible'] == 0)
{
++$num_unapproved_posts;
}
else
{
++$num_approved_posts;
}
$plugins->run_hooks("class_moderation_delete_post", $post['pid']);
// Update stats
$update_array = array(
"replies" => "-{$num_approved_posts}",
"unapprovedposts" => "-{$num_unapproved_posts}"
);
update_thread_counters($post['tid'], $update_array);
// Update stats
$update_array = array(
"posts" => "-{$num_approved_posts}",
"unapprovedposts" => "-{$num_unapproved_posts}"
);
update_forum_counters($post['fid'], $update_array);
return true;
}
function backup_post($pid)
{
global $mybb, $db, $cache, $plugins;
// Get pid, uid, fid, tid, visibility, forum post count status of post
$pid = intval($pid);
$query = $db->query("
SELECT p.pid, p.uid, p.fid, p.tid, p.visible, f.usepostcounts, t.visible as threadvisible, message, p.username as p_username, p.subject, p.dateline
FROM ".TABLE_PREFIX."posts p
LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid)
LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid)
WHERE p.pid='$pid'
");
$post = $db->fetch_array($query);
$deletedpost = array(
"username_delete" => $mybb->user['username'],
"username" => $post['p_username'],
"subject" => $post['subject'],
"message" => $post['message'],
"dateline" => TIME_NOW,
"post_dateline" => $post['dateline'],
);
$db->insert_query("posts_deleted", $deletedpost);
//14-06-20016
//ob_start();
//var_dump($mybb);
//$data = ob_get_clean();
//$fp = fopen(MYBB_ROOT."myText.txt","wb");
//fwrite($fp,$data);
//fwrite($fp, "cancellato da ".$mybb->user['username']);
//fwrite($fp, "autore ".$post['p_username']);
//fwrite($fp, "messaggio ".$post['message']);
/*
foreach ($post as $key => $value) {
fwrite($fp, $key );
}
*/
//fclose($fp);
return true;
}
You are adding functions to a class (then we tend to call them "methods" instead of "functions", but that doesn't really matter).
When you want to call a class method, you need to call it like $class_instance->method_name() instead of the usual method_name(), which works for "plain" functions.
When you are calling a method from another method in the same class, you use $this to get the same class instance.
So if you change this line:
backup_post($pid);
to:
$this->backup_post($pid);
it should work.

how to discover last id after delete and set new autoincrement mysql data line

i have a question, im deleting data from mysql by id in 2 tables, but on sales table i want to keep the same id after delete. And when i add a new sale keep the last deleted id.
For example, i have sale id nr 100 on delete and on create a new sale the id will be 101.
What i want is to keep 100 if i delete.
this is my model based on codeigniter:
public function getAllInvoiceItems($sale_id)
{
$q = $this->db->get_where('sale_items', array('sale_id' => $sale_id));
if($q->num_rows() > 0) {
foreach (($q->result()) as $row) {
$data[] = $row;
}
return $data;
}
}
public function getInvoiceByID($id)
{
$q = $this->db->get_where('sales', array('id' => $id), 1);
if( $q->num_rows() > 0 )
{
return $q->row();
}
return FALSE;
}
public function deleteInvoice($id)
{
$inv = $this->getInvoiceByID($id);
$warehouse_id = $inv->warehouse_id;
$items = $this->getAllInvoiceItems($id);
foreach($items as $item) {
$product_id = $item->product_id;
$item_details = $this->getProductQuantity($product_id, $warehouse_id);
$pr_quantity = $item_details['quantity'];
$inv_quantity = $item->quantity;
$new_quantity = $pr_quantity + $inv_quantity;
$this->updateQuantity($product_id, $warehouse_id, $new_quantity);
}
if($this->db->delete('sale_items', array('sale_id' => $id)) && $this->db->delete('sales', array('id' => $id))) {
return true;
}
return FALSE;
}

Symfony2 , improve query performance

Does anybody know how to improve performance of this query?
I'm using doctrine DQL model, here's the code
(it takes 5-6 sec without pagination bundle)
Controller:
$data = $this->getDoctrine()
->getEntityManager('sparcs')
->getRepository('TruckingMainBundle:BCT_CNTR_EVENTS')
->findOperationReport(Convert::serializeToArray($request->getContent()));
Repository method:
public function findOperationReport($condition = array()) {
$data = $condition['record'];
$move_types = array();
$result = $this->createQueryBuilder("sp")
->addSelect("sp");
// move types
if(isset($data['vessel_discharge'])) {
//$move_types[] = $this->container->getParameter('MOVE_TYPE.VESSEL_DIS');
$move_types[] = 'VY';
}
if(isset($data['vessel_loading'])) {
//$move_types[] = $this->container->getParameter('MOVE_TYPE.VESSEL_LOAD');
$move_types[] = 'YV';
}
if(isset($data['truck_out'])) {
$move_types[] = 'TC';
}
if(isset($data['truck_in'])) {
$move_types[] = 'CT';
}
if(isset($data['stuffing'])) {
//$move_types[] = 'CT';
}
if(isset($data['unstuffing'])) {
//$move_types[] = 'CT';
}
if(isset($data['rail_in'])) {
$move_types[] = 'YR';
}
if(isset($data['rail_out'])) {
$move_types[] = 'RY';
}
if(count($move_types) > 0) {
$result->andWhere('sp.move_type IN (:move_type)')
->setParameter('move_type',$move_types);
} else {
$result->andWhere("1 = 2");
}
//container types
if(isset($data['empty']) && isset($data['full'])) {
//skipping
}
elseif (isset($data['empty'])) {
$result->andWhere('sp.ctnr_status = :ctnr_status')
->setParameter('ctnr_status',self::CTNR_EMPTY);
}
elseif (isset($data['full'])) {
$result->andWhere('sp.ctnr_status = :ctnr_status')
->setParameter('ctnr_status',self::CTNR_FULL);
if(isset($data['weight_from'])) {
$result->andWhere("cast(replace([weight],',','.') as float) :weight_from")
->setParameter('weight_from',$data['weight_from']);
echo 'weight from';
}
if(isset($data['weight_to'])) {
$result->andWhere('sp.weight <= :weight_to')
->setParameter('weight_to',(string)$data['weight_to']);
}
}
/*
//excpetion
$result->andWhere('sp.move_type NOT IN (:move_type_not)')
->setParameter('move_type_not',array('TY','YT'));
*/
if(isset($data['today']) || isset($data['yesterday'])) {
//yesterday
if(isset($data['yesterday'])) {
$yesterday = new \DateTime(date("Ymd"));
$interval = new \DateInterval("P1D");
$interval->invert = 1;
$yesterday->add($interval);
}
//yesterday + today
if(isset($data['today']) && isset($data['yesterday'])) {
$result->andWhere('sp.move_time >= :yesterday')
->setParameter('yesterday',$yesterday->format("Ymd000000"));
}
elseif(isset($data['yesterday'])) {
$result->andWhere('sp.move_time >= :yesterday_from AND sp.move_time <= :yesterday_to')
->setParameter('yesterday_from',$yesterday->format("Ymd000000"))
->setParameter('yesterday_to',$yesterday->format("Ymd235959"));
}
elseif(isset($data['today'])) {
$result->andWhere("sp.move_time = :today")
->setParameter('today',date("Ymd000000"));
}
}
else {
//date conditions
$date_from = new \DateTime(strtotime($data['date_from']));
$date_to = new \DateTime(strtotime($data['date_to']));
$result->andWhere("sp.move_time >= :date_from")
->setParameter('date_from',$date_from->format("Ymd000000"));
$result->andWhere("sp.move_time <= :date_to")
->setParameter('date_to',$date_to->format("Ymd235959"));
}
//booking
if(isset($data['booking']) && !empty($data['booking'])) {
$result->andWhere("sp.booking = :booking")
->setParameter('booking',$data['booking']);
}
//is reffer
if(isset($data['reefer'])) {
$result->andWhere("sp.reefer_flag = :reefer")
->setParameter('reefer','Y');
}
//is damage
if(isset($data['damage'])) {
$result->andWhere("sp.hazards <> ''"); //$result->expr()->neq("sp.hazards","")
}
//specific_type
if(isset($data['specific_type'])) {
/*
$result->andWhere("sp.equip_type <> :specific_type")
->setParameter('specific_type',$data['specific_type']);
*
*/
}
//specific_type
if(isset($data['container_type_20']) && isset($data['container_type_40'])) {
//$result->andWhere("sp.equip_type <> :specific_type")
// ->setParameter('specific_type',$data['specific_type']);
}
elseif(isset($data['container_type_20'])) {
$result->andWhere($result->expr()->substring('sp.equip_type',1,1)." = :equip_type")
->setParameter('equip_type',2);
}
elseif(isset($data['container_type_40'])) {
$result->andWhere($result->expr()->substring('sp.equip_type',1,1)." = :equip_type")
->setParameter('equip_type',4);
}
return $result->setMaxResults(30)->getQuery();
}
If I use KnpPaginationBundle ,then it takes more than 27 sec )
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$data,
2/*page number*/,
10/*limit per page*/
);
I can execute a native sql query without KnpPaginatorBundle (and it takes 0.333 ms)
//START
$query = $this->getDoctrine()
->getEntityManager('sparcs')->getConnection()->executeQuery (
'SELECT *
FROM (SELECT Row_number()
OVER (
ORDER BY (SELECT 0)) AS "doctrine_rownum",
b0_.id AS id0,
b0_.container AS container1,
b0_.container_use_key AS container_use_key2,
b0_.line AS line3,
b0_.billable_line AS billable_line4,
b0_.move_time AS move_time5,
b0_.move_type AS move_type6,
b0_.pos_from AS pos_from7,
b0_.pos_to AS pos_to8,
b0_.rotation_nbr AS rotation_nbr9,
b0_.from_che AS from_che10,
b0_.to_che AS to_che11,
b0_.from_che_kind AS from_che_kind12,
b0_.to_che_kind AS to_che_kind13,
b0_.from_che_op AS from_che_op14,
b0_.to_che_op AS to_che_op15,
b0_.pow AS pow16,
b0_.internal_truck AS internal_truck17,
b0_.lifter AS lifter18,
b0_.quay_crane AS quay_crane19,
b0_.license_plate AS license_plate20,
b0_.trucker_id AS trucker_id21,
b0_.trucker_name AS trucker_name22,
b0_.arrv_qual AS arrv_qual23,
b0_.arrv_carrier AS arrv_carrier24,
b0_.dept_qual AS dept_qual25,
b0_.dept_carrier AS dept_carrier26,
b0_.invoyage AS invoyage27,
b0_.outvoyage AS outvoyage28,
b0_.lloyds_code AS lloyds_code29,
b0_.load_port AS load_port30,
b0_.disch_port AS disch_port31,
b0_.destination AS destination32,
b0_.equip_type AS equip_type33,
b0_.bundle AS bundle34,
b0_.ctnr_category AS ctnr_category35,
b0_.ctnr_status AS ctnr_status36,
b0_.ctnr_stopped AS ctnr_stopped37,
b0_.commodity AS commodity38,
b0_.weight AS weight39,
b0_.damage AS damage40,
b0_.reefer_temp AS reefer_temp41,
b0_.reefer_flag AS reefer_flag42,
b0_.damage_details AS damage_details43,
b0_.seal_1 AS seal_144,
b0_.railcar_id AS railcar_id45,
b0_.dwell_time AS dwell_time46,
b0_.special_stow AS special_stow47,
b0_.service AS service48,
b0_.booking AS booking49,
b0_.release_note AS release_note50,
b0_.cmr_number AS cmr_number51,
b0_.forwarding_agent AS forwarding_agent52,
b0_.cargo_agent AS cargo_agent53,
b0_.invoice_number AS invoice_number54,
b0_.invoice_status AS invoice_status55,
b0_.last_flag AS last_flag56,
b0_.sparcs_user AS sparcs_user57,
b0_.program AS program58,
b0_.id AS id59,
b0_.container AS container60,
b0_.container_use_key AS container_use_key61,
b0_.line AS line62,
b0_.billable_line AS billable_line63,
b0_.move_time AS move_time64,
b0_.move_type AS move_type65,
b0_.pos_from AS pos_from66,
b0_.pos_to AS pos_to67,
b0_.rotation_nbr AS rotation_nbr68,
b0_.from_che AS from_che69,
b0_.to_che AS to_che70,
b0_.from_che_kind AS from_che_kind71,
b0_.to_che_kind AS to_che_kind72,
b0_.from_che_op AS from_che_op73,
b0_.to_che_op AS to_che_op74,
b0_.pow AS pow75,
b0_.internal_truck AS internal_truck76,
b0_.lifter AS lifter77,
b0_.quay_crane AS quay_crane78,
b0_.license_plate AS license_plate79,
b0_.trucker_id AS trucker_id80,
b0_.trucker_name AS trucker_name81,
b0_.arrv_qual AS arrv_qual82,
b0_.arrv_carrier AS arrv_carrier83,
b0_.dept_qual AS dept_qual84,
b0_.dept_carrier AS dept_carrier85,
b0_.invoyage AS invoyage86,
b0_.outvoyage AS outvoyage87,
b0_.lloyds_code AS lloyds_code88,
b0_.load_port AS load_port89,
b0_.disch_port AS disch_port90,
b0_.destination AS destination91,
b0_.equip_type AS equip_type92,
b0_.bundle AS bundle93,
b0_.ctnr_category AS ctnr_category94,
b0_.ctnr_status AS ctnr_status95,
b0_.ctnr_stopped AS ctnr_stopped96,
b0_.commodity AS commodity97,
b0_.weight AS weight98,
b0_.damage AS damage99,
b0_.reefer_temp AS reefer_temp100,
b0_.reefer_flag AS reefer_flag101,
b0_.damage_details AS damage_details102,
b0_.seal_1 AS seal_1103,
b0_.railcar_id AS railcar_id104,
b0_.dwell_time AS dwell_time105,
b0_.special_stow AS special_stow106,
b0_.service AS service107,
b0_.booking AS booking108,
b0_.release_note AS release_note109,
b0_.cmr_number AS cmr_number110,
b0_.forwarding_agent AS forwarding_agent111,
b0_.cargo_agent AS cargo_agent112,
b0_.invoice_number AS invoice_number113,
b0_.invoice_status AS invoice_status114,
b0_.last_flag AS last_flag115,
b0_.sparcs_user AS sparcs_user116,
b0_.program AS program117
FROM bct_cntr_events b0_
WHERE b0_.move_type IN ( \'YY\',\'YV\',\'VY\',\'TY\' )
AND b0_.move_time >= \'20120910000000\'
AND b0_.move_time <= \'20120912300000\') AS doctrine_tbl
WHERE "doctrine_rownum" BETWEEN 11 AND 20 '
)->fetchAll();
Think about add memcache as a cache driver.
Think about stopping hydrating results to entity objects (time & cpu consuming)
$query->getResult(Query::HYDRATE_ARRAY);
Avoid conditions with wildcard strings.
Try PagerFanta.

Magento BestSeller Module - Summing Configurable Products And Adding Them Back In

This has been bugging me for quite a while. Basically, what we are trying to achieve is in the bestsellers on our front page, to have the products listed in the amount sold. For simple products this works fine, however for configurable products they will be displayed as a quantity ordered of 0.
I somehow need to find a way to get the configurable products, find the simple products attached to them, sum the amount sold of these simple products, add this back to the configurable products ID and feed this information back in so it will list the configurable product with the right amount that has been sold.
I have placed, what I believe, the areas of code that require changing. If anyone could help it would be very much appreciated!
Collection.php
class Luxe_Bestsellers_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection
{
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
$this->getSelect()
->joinInner(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('e.entity_id')
->having('ordered_qty > 0');
return $this;
}
}
List.php
class Luxe_Bestsellers_Block_List extends Mage_Catalog_Block_Product_List
{
protected $_defaultToolbarBlock = 'bestsellers/list_toolbar';
protected function _beforeToHtml() {
$this->addPriceBlockType('bundle', 'bundle/catalog_product_price', 'bundle/catalog/product/price.phtml');
return parent::_beforeToHtml();
}
public function _toHtml()
{
if ($this->_productCollection->count()) {
return parent::_toHtml();
} else {
return '';
}
}
public function getTimeLimit()
{
if ($this->getData('time_limit_in_days')) {
return intval($this->getData('time_limit_in_days'));
} else {
return intval(Mage::getStoreConfig('bestsellers/bestsellers/time_limit_in_days'));
}
}
public function getBlockTitle()
{
if ($this->getData('title')) {
return $this->getData('title');
} else {
return Mage::getStoreConfig('bestsellers/bestsellers/title');
}
}
public function isShowOutOfStock() {
return (bool)Mage::getStoreConfig('bestsellers/bestsellers/show_out_of_stock');
}
public function getProductsLimit()
{
if ($this->getData('limit')) {
return intval($this->getData('limit'));
} else {
return $this->getToolbarBlock()->getLimit();
}
}
public function getDisplayMode()
{
return $this->getData('display_mode');
}
/**
* Retrieve loaded category collection
*
* #return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getModel('catalog/layer');
$bestsellers = Mage::getResourceModel('reports/product_collection');
if ($this->getTimeLimit()) {
$product = Mage::getModel('catalog/product');
$todayDate = $product->getResource()->formatDate(time());
$startDate = $product->getResource()->formatDate(time() - 60 * 60 * 24 * $this->getTimeLimit());
$bestsellers->addOrderedQty($startDate, $todayDate, true);
} else {
$bestsellers->addOrderedQty('', '', true);
}
$bestsellers->addStoreFilter()
->setOrder('ordered_qty', 'desc')
->setPageSize($this->getProductsLimit());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($bestsellers);
if ($layer->getCurrentCategory()->getId() != Mage::app()->getStore()->getRootCategoryId()) {
$bestsellers->addCategoryFilter($layer->getCurrentCategory());
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bestsellers);
}
if (!$this->isShowOutOfStock()) {
Mage::getModel('cataloginventory/stock')->addInStockFilterToCollection($bestsellers);
}
$bestsellers->getSelect()->where('order.store_id = ?', Mage::app()->getStore()->getId());
$productIds = array();
foreach ($bestsellers as $p) {
$productIds[] = $p->getId();
}
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$collection->addIdFilter($productIds)
->addAttributeToSelect($attributes)
->addMinimalPrice()
->addFinalPrice();
$this->_productCollection = $collection;
}
return $this->_productCollection;
}
/**
* Translate block sentence
*
* #return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mage_Catalog');
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
}
Thanks for posting that sample code! I was able to use it to create a solution which should work well for both of us.
I found that configurable product sales are being summed correctly but aren't being included in the results; their child products appear instead. My solution was to include configurable products, do a left join on the catalog_product_super_link table, and filter out anything that has a parent_id. Here are the changes you'll need to make:
Collection.php:
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false, $getComplexChildProducts = true, $getRemovedProducts = true)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array(
'ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})",
'order_items_name' => 'order_items.name'
)
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
// Add join to get the parent id for configurables
$this->getSelect()->joinLeft(
array('cpsl' => $this->getTable('catalog/product_super_link')),
'cpsl.product_id = order_items.product_id',
'cpsl.parent_id'
);
if(!$getComplexChildProducts)
$this->getSelect()->having('parent_id IS NULL');
if($getRemovedProducts)
{
$this->getSelect()
->joinLeft(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('order_items.product_id');
}
else
{
$this->getSelect()
->joinInner(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('e.entity_id');
}
$this->getSelect()->having('ordered_qty > 0');
// This line is for debug purposes, in case you'd like to see what the SQL looks like
// $x = $this->getSelect()->__toString();
return $this;
}
List.php - Find the following two lines...
$bestsellers->addOrderedQty($startDate, $todayDate, true);
$bestsellers->addOrderedQty('', '', true);
... and change them to:
$bestsellers->addOrderedQty($startDate, $todayDate, true, false, false);
$bestsellers->addOrderedQty('', '', true, false, false);
My changes added two new optional parameters, which both default to true, as to not break existing functionality.
When $getComplexChildProducts is set to false, all child items of the configurable product will be removed from the results.
$getRemovedProducts determines whether or not previously ordered products (which have since been deleted from Magento) should also appear.
Please note that your report statistics will need to be up-to-date in order to get accurate results.
Hope this helps! Let me know if you have any questions.
You can use the following piece of code to get the simple products attached to the configurable product. I'm not sure if this is 100% correct, I haven't tried it myself.
$simpleProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);

Categories