I try to inject some optional SQL to prepared statement with the parameter $and:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and, $returnArray = false)
{
if (!isset($property_id) || empty($property_id)
|| !isset($property_item_type_id) || empty($property_item_type_id)
|| !isset($and) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $this->con->real_escape_string($and) // <--- here
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$err = "";
if (!$stmt = $this->con->prepare($sql)) {
$err .= "Prepare failed: (" . $this->con->errno . ") " . $this->con->error;
}
...
But if I call the function e.g.
$row2 = Main::getModel("Property/Item")->loadInfoAndStatus(
$id
, $property_item_type_id
, " AND c.iso = 'DE' "
, true
);
Hint: $and can be one of:
" AND c.iso <> 'DE' AND c.european <> 1 "
" AND c.iso <> 'DE' AND c.european = 1 "
" AND c.iso = 'DE' "
Then I get "Prepare failed" but there is no error message.
Resulting SQL:
SELECT pi.status, pi.info, pi.property_item_id FROM property_item pi JOIN countries c ON c.country_id = pi.country_id WHERE pi.property_id = ? AND property_item_type_id = ? AND c.iso = \'DE\' ORDER BY pi.status DESC LIMIT 0,1
It works if I don't use real_escape_string
Do I have to create new functions for each new sql, or is there another way?
You have to list all possible variants in your function.
This is a toilsome task but you have to realize that's the only way.
public function loadInfoAndStatus($property_id, $property_item_type_id, $iso = null, $european = null, $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
$parameters = [$property_id, $property_item_type_id];
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? ";
if ($iso) {
$sql .= " AND c.iso <> ? ";
$parameters[] = $iso;
}
if ($european === true) {
$sql .= " AND c.european == 1 ";
} elseif ($european === false) {
$sql .= " AND c.european <> 1 ";
}
$sql .= " ORDER BY pi.status ";
$sql .= " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
$stmt->bind_param(str_repeat("s", count($parameters)), ...$parameters);
$stmt->execute();
I also removed some cargo cult code from your method, in case you are interested why
Do you really need to check for both isset() and empty() at the same time?
PHP error reporting
I solved the problem by using a whitelist method:
public function loadInfoAndStatus($property_id, $property_item_type_id, $and = "", $returnArray = false)
{
if (empty($property_id) || empty($property_item_type_id) || empty($and)) {
error_log(get_class() . " - " . __FUNCTION__ ." : required params not set or empty");
return false;
}
if (!$this->isSqlInWhitelist($and, array(
"AND c.iso = 'DE'"
,"AND c.iso <> 'DE' AND c.european = 1"
,"AND c.iso <> 'DE' AND c.european <> 1"
))) {
error_log(get_class() . " - " . __FUNCTION__ ." : sql is not in whitelist.");
return false;
}
$sql = " SELECT pi.status, pi.info, pi.property_item_id "
. " FROM ". self::TABLE ." pi "
. " JOIN countries c ON c.country_id = pi.country_id "
. " WHERE pi.property_id = ? "
. " AND property_item_type_id = ? "
. $and
. " ORDER BY pi.status "
. " DESC LIMIT 0,1";
$stmt = $this->con->prepare($sql);
...
...
protected function isSqlInWhitelist($sql, $whitelist)
{
if (!empty($sql)) {
if (!in_array(trim($sql), $whitelist)) { return false; }
}
return true;
}
Related
I have this .Net REST API function modified from the demo for a grid control here: http://gijgo.com/grid/demos/ajax-sourced-data.
However, I am using PHP on the backend.
public JsonResult Get(int? page, int? limit)
{
List<Models.inventory> records;
int total;
using (ApplicationDbContext context = new ApplicationDbContext())
{
var query = context.inventory.Select(p => new Models.inventory
{
id = p.id,
company = p.company,
part = p.part,
year = p.year,
model = p.model,
stock = p.stock,
ic = p.ic,
vin = p.vin,
status = p.status,
bodycolor = p.bodycolor,
condition = p.condition,
comments = p.comments,
miles = p.miles,
price = p.price,
qty = p.qty
});
query = query.OrderBy(q => q.id);
total = query.Count();
if (page.HasValue && limit.HasValue)
{
int start = (page.Value - 1) * limit.Value;
records = query.Skip(start).Take(limit.Value).ToList();
}
else
{
records = query.ToList();
}
}
return this.Json(new { records, total }, JsonRequestBehavior.AllowGet);
}
I have converted the function to PHP but am having difficulty with the pagination because the total records isn't really being sent.
The C# code, filters the data after the query and i'm not sure how to do that with PHP and PostgreSQL.
I also want to return the total number of rows without the limit and offset in the result I suppose I'm going to have to run a 2nd query to return that data,
is that correct or can I do it in another way?
private function GetInventory()
{
$ic=$_request['ic'];
$limit=$_request['limit'];
$offset=$_request['page']-1;
$sql = "SELECT u.id, "
. " (SELECT company FROM urgss.users WHERE id = u.id) AS company, "
. " u.itemname || ' (' || u.part || ')' as part, "
. " u.year, "
. " u.model, "
. " u.stockno AS stock, "
. " u.ic AS ic, "
. " u.vin, "
. " u.status || ' / ' || u.currentstatus AS status, "
. " REGEXP_REPLACE(u.bod_col, '[\[\]]', '', 'g') AS bodycolor, "
. " u.condition, "
. " u.comments, "
. " CASE "
. " WHEN u.miles::integer < 1000 THEN "
. " u.miles::INTEGER * 1000 "
. " ELSE "
. " u.miles::INTEGER "
. " END AS miles, "
. " CASE "
. " WHEN u.rprice > 0 THEN "
. " u.rprice "
. " ELSE "
. " NULL "
. " END AS price, "
. " u.qty "
. "FROM unet u "
. "WHERE ic = '" . $ic. "' "
. "AND year::integer > 0"
. " LIMIT " . $limit . " OFFSET ". ($offset * $limit);
$result = pg_exec($db, $sql);
$rows = pg_fetch_all($result);
echo json_encode($rows);
}
If you remove LIMIT from the query (REMOVE THIS . " LIMIT " . $limit . " OFFSET ". ($offset * $limit);), then there are two options:
Instead of pg_fetch_all you could fetch in a loop and specify the $row_num based on offset and limit:
//get total number of rows
$total = pg_num_rows($result);
//get rows from offset up to limit
$row_num = $offset;
while($row_num < ($offset + $limit) && $rows[] = pg_fetch_assoc($result, $row_num)) {
$row_num++;
}
echo json_encode($rows);
Or pg_fetch_all and slice what you want:
//get total number of rows
$total = pg_num_rows($result);
//get ALL rows
$rows = pg_fetch_all($result);
//get rows from offset up to limit
$rows = array_slice($rows, $offset, $limit);
echo json_encode($rows);
Not sure what new { records, total } does in .NET, but you could return one of these:
return json_encode([$rows, $total]);
//or
return json_encode(['rows' => $rows, 'total' => $total]);
Here I want to assign $part1 and $part2 value into Mysqli query. But what is the problem is $part2 value does not get into query. I could not be able to find what would be the wrong with my code.
$string = 'Enter a domain name' . "\r\n";
socket_write($client, $string, strlen($string)) or die("Could not write output\n");
$str = '';
while ($input = socket_read($client, 1024)) {
$str .= $input;
if (strpos($str, "\n") !== false) {
break 1;
}}
$part = explode(".", $str);
$part1 = $part[0];
$part2= $part[1];
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='$part1' "
. "AND DomainNameType.Name='$part2' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
$result = $mysqli->query($sql);
$row1 = $result->num_rows;
if ($row1 > 0) {
$row = $result->fetch_array(MYSQLI_NUM);
printf("%s\n", $row[0]);
} else {
echo 'This is not a Registered Domain';
}
Connect with PDO
try
{
$dbh = new PDO("pgsql:host=$host;port=5432;dbname=$db;user=$user;password=$pass");
echo "Connected";
}
catch (Exception $e)
{
echo "Unable to connect: " . $e->getMessage() ."";
}
Prepare your statment:
$sth = $dbh->prepare("SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='?' "
. "AND DomainNameType.Name='?' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID");
And Execute:
`enter code here`
$sth->execute(array($part1, $part2));
$red = $sth->fetchAll();
As suggested by Combinu, PDO is the better way to go. However, to go along with your idea, I would concatenate the content of the variables.
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name= ". $part1
. "AND DomainNameType.Name= " . $part2
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
Use {$part2} and also check that $part2 has value after asignment
$sql = "SELECT DomainCategory.Name "
. "FROM DomainName_Client, DomainNameType, DomainCategory, OrderDomain_Client "
. "WHERE DomainName_Client.Name='{$part1}' "
. "AND DomainNameType.Name='{$part2}' "
. "AND DomainName_Client.TypeID=DomainNameType.ID "
. "AND DomainCategory.ID=DomainName_Client.DomainCategoryID "
. "AND OrderDomain_Client.DomainNameID=DomainName_Client.ID";
Use Join Query rather then simple select Query with where condition
`"SELECT DomainCategory.Name FROM DomainName_Client join DomainNameType on DomainNameType.ID = DomainName_Client.TypeID join DomainCategory on DomainCategory.ID=DomainName_Client.DomainCategoryID join OrderDomain_Client on OrderDomain_Client.DomainNameID=DomainName_Client.ID WHERE DomainName_Client.Name = '".$part1."' AND DomainNameType.Name = '".$part2."'";`
I am trying to make ONE dynamic function for count in mysql:
functions.php:
function countEntries($table, $where = '', $what = '')
{
if (!empty($where) && isset($what)) {
$q = "SELECT COUNT(*) FROM " . $table . " WHERE " . $where . " = '" . $what . "' LIMIT 1";
} else{
$q = "SELECT COUNT(*) FROM " . $table . " LIMIT 1";
}
$record = query($q);
$total = fetchrow($record);
return $total[0];
}
HTML Code:
<?php echo countEntries("news", "category", "1"); ?>
<?php echo countEntries("post", "type", "Sports"); ?>
But still got blank page without any error!!!
You can try this out.
function countEntries($table, $where = '', $what = '')
{
if (!empty($where) && isset($what)) {
$q = "SELECT COUNT(*) AS count FROM " . $table . " WHERE " . $where . " = '" . $what . "' LIMIT 1";
} else{
$q = "SELECT COUNT(*) AS count FROM " . $table . " LIMIT 1";
}
$record = query($q);
$total = fetchrow($record);
return $total['count'];
}
Here you give an alias to the count(*) and use that to access the returned result as $total['count'].
Hope it helps.
First things you forgot to close else past,second just add this line "ini_set("display_errors", 1);" at the top of your php.this will shows the error in your php.
Your code:
function countEntries($table, $where = '', $what = '')
{
if (!empty($where) && isset($what)) {
$q = "SELECT COUNT(*) FROM " . $table . " WHERE " . $where . " = '" . $what . "' LIMIT 1";
} else
$q = "SELECT COUNT(*) FROM " . $table . " LIMIT 1";
}
$record = query($q);
$total = fetchrow($record);
return $total[0];
}
my code:
function countEntries($table, $where = '', $what = '')
{
if (!empty($where) && isset($what)) {
$q = "SELECT COUNT(*) AS count FROM " . $table . " WHERE " . $where . " = '" . $what . "' LIMIT 1";
} else{
$q = "SELECT COUNT(*) AS count FROM " . $table . " LIMIT 1";
}
$record = query($q);
$total = fetchrow($record);
return $total['count'];
}
Thanks guys, Its working well now:
function countEntries($table, $where, $what)
{
if (!empty($where) && isset($what)) {
$q = "SELECT COUNT(*) FROM " . $table . " WHERE " . $where . " = '" . $what . "' LIMIT 1";
} else
$q = "SELECT COUNT(*) FROM " . $table . " LIMIT 1";
$record = mysql_query($q);
$total = mysql_fetch_array($record);
return $total[0];
}
echo countEntries('news', "type", "sport");
I am working on an update query where the values should only update when the value is not null or empty. Now it updates everything regardless the value. Please help me out with this one.
$query = "UPDATE bundels
SET batchkosten = CASE WHEN ". $_POST['batchkosten'] . " IS NOT NULL
THEN ". $_POST['batchkosten'] . "
ELSE batchkosten
END CASE,
CASE WHEN ". $_POST['maandelijkse_kosten'] . " IS NOT NULL
THEN ". $_POST['maandelijkse_kosten'] . "
ELSE maandelijkse_kosten
END CASE,
CASE WHEN ". $_POST['aanmeldkosten'] . " IS NOT NULL
THEN ". $_POST['aanmeldkosten'] . "
ELSE aanmeldkosten
END CASE,
CASE WHEN ". $_POST['transactiekosten'] . " IS NOT NULL
THEN ". $_POST['transactiekosten'] . "
ELSE transactiekosten
END CASE,
CASE WHEN ". $_POST['referral'] . " IS NOT NULL
THEN ". $_POST['referral'] . "
ELSE referral
END CASE,
CASE WHEN ". $_POST['actief'] . " IS NOT NULL
THEN ". $_POST['actief'] . "
ELSE actief
END CASE
WHERE bundel_id = ". $_POST['bundel_id'] . "";
$result = mysql_query($query, $db) or die ('FOUT: werkt niet');
header ("Location: vergelijker_bewerken.php");
} else {
$bundels = mysql_query("SELECT bundels.psp_id, psp.psp_id, psp_naam, bundels.bundel_id, batchkosten, maandelijkse_kosten, aanmeldkosten, transactiekosten, referral, actief from bundels
JOIN psp
ON psp.psp_id = bundels.psp_ID");
}
Use Prepared Statements to escape user input and avoid SQL syntax errors and SQL injections.
You can use a case
UPDATE bundels
SET batchkosten = case when ? is not null and length(?) > 0
then ?
else batchkosten
end,
...
Your current query translates to (which should throw an error actually)
UPDATE bundels
SET batchkosten = CASE WHEN ? length(?) > 0
THEN ?
ELSE batchkosten
END
WHERE bundel_id = ?
But use instead:
SET batchkosten = CASE WHEN ? is not null and length(?) > 0
you can write script some like this maybe:
$query = "Update bundels SET ";
$columns = array( "batchkosten",
"maandelijkse_kosten",
"aanmeldkosten",
"transactiekosten",
"referral",
"actief");
foreach($columns as $column){
if(isset($_POST[$column]) && !empty($_POST[$column])){
$query .= $column . " = " $_POST[$column] . " ";
}
}
$query .= " WHERE bundel_id = " . $_POST['bundel_id'];
Change the query to this
$query= "UPDATE bundels SET
batchkosten = ' ". $_POST['batchkosten'] . " ',
maandelijkse_kosten = ' ". $_POST['maandelijkse_kosten'] . " ',
aanmeldkosten = ' ". $_POST['aanmeldkosten'] . " ',
transactiekosten = ' ". $_POST['transactiekosten'] . " ',
referral = ' ". $_POST['referral'] . " ',
actief = ' ". $_POST['actief'] . " '
WHERE bundel_id = ". $_POST['bundel_id'] . " ".
"and your_attribut is not null and your_attribut != ''";
Don't forget to change "your_attribut".
I have implemented jsTree on my site with a php/MySQL back-end for tree storage and retrieval. I used the php/MySQL demo that came with the jsTree download for the basic infrastructure and then modified to my needs.
I have modified so that multiple trees can be stored in the same database, and added a new column of "owner_id" that stores the userid of the person that created that particular tree.
The php code that creates a new branch or moves a branch is not working correctly as it is not taking into account that there are multiple trees within the database.
jsTree uses the nested set model, and the script is adjusting the left and right values of all the trees in the database instead of just the one that has had a new branch added. This is slowly corrupting the entire database.
The following code shows the function/s that does the adjusting, could someone please try and amend the code for me so it uses the "owner_id" field to only make the changes to a particular tree?
function _create($parent, $position) {
return $this->_move(0, $parent, $position);
}
and then...
function _move($id, $ref_id, $position = 0, $is_copy = false) {
$hbhbhbh = fSession::get('nodes_allowed[nodes_access]');
if ($hbhbhbh == "0" || $hbhbhbh == "2" || $hbhbhbh == "3") {
if((int)$ref_id === 0 || (int)$id === 1) { return false; }
$sql = array(); // Queries executed at the end
$node = $this->_get_node_ifuueuwyhddd($id); // Node data
$nchildren = $this->_get_children($id); // Node children
$ref_node = $this->_get_node_ifuueuwyhddd($ref_id); // Ref node data
$rchildren = $this->_get_children($ref_id);// Ref node children
$ndif = 2;
$node_ids = array(-1);
if($node !== false) {
$node_ids = array_keys($this->_get_children($id, true));
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes
if(in_array($ref_id, $node_ids)) return false;
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
}
if($position >= count($rchildren)) {
$position = count($rchildren);
}
// Not creating or copying - old parent is cleaned
if($node !== false && $is_copy == false) {
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
}
// Preparing new parent
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
"`".$this->fields["position"]."` >= ".$position." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
$ref_ind = max($ref_ind, 1);
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
foreach($rchildren as $k => $v) {
if($v[$this->fields["position"]] - $self == $position) {
$ref_ind = (int)$v[$this->fields["left"]];
break;
}
}
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
$ref_ind -= $ndif;
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["left"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["right"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
$idif = $ref_ind;
if($node !== false) {
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
$idif = $node[$this->fields["left"]] - $ref_ind;
if($is_copy) {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."`" .
") " .
"SELECT " .
"".$ref_id.", " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["level"]."` - (".$ldif.") " .
"FROM `".$this->table."` " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
"ORDER BY `".$this->fields["level"]."` ASC";
}
else {
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["parent_id"]."` = ".$ref_id.", " .
"`".$this->fields["position"]."` = ".$position." " .
"WHERE " .
"`".$this->fields["id"]."` = ".$id;
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
}
}
else {
$ewre = fSession::get('user[user_id]');
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["owner"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
$ewre.", " .
$ref_id.", " .
$position.", " .
$idif.", " .
($idif + 1).", " .
$ldif.
")";
}
foreach($sql as $q) { $this->db->query($q); }
$ind = $this->db->insert_id();
if($is_copy) $this->_fix_copy($ind, $position);
return $node === false || $is_copy ? $ind : true;
}
}
Any help really appreciated.
Thanks
For anyone else this might help, here is my code after the changes to I made to make creating / moving nodes only apply to the particular tree in question.
Adding the owner_id in the where clause did in fact fix the issue. I needed to add it to only certain queries:
function _move($id, $ref_id, $position = 0, $is_copy = false) {
$hbhbhbh = fSession::get('nodes_allowed[nodes_access]');
if ($hbhbhbh == "0" || $hbhbhbh == "2" || $hbhbhbh == "3") {
if((int)$ref_id === 0 || (int)$id === 1) { return false; }
$sql = array(); // Queries executed at the end
$node = $this->_get_node_ifuueuwyhddd($id); // Node data
$nchildren = $this->_get_children($id); // Node children
$ref_node = $this->_get_node_ifuueuwyhddd($ref_id); // Ref node data
$rchildren = $this->_get_children($ref_id);// Ref node children
$ndif = 2;
$node_ids = array(-1);
if($node !== false) {
$node_ids = array_keys($this->_get_children($id, true));
// TODO: should be !$is_copy && , but if copied to self - screws some right indexes
if(in_array($ref_id, $node_ids)) return false;
$ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
}
if($position >= count($rchildren)) {
$position = count($rchildren);
}
// Not creating or copying - old parent is cleaned
if($node !== false && $is_copy == false) {
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]]." AND " .
"`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
"`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
"WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]]." AND " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]];
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $node[$this->fields["owner"]]." AND " .
"`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
"`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
"WHERE " .
"`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
"`".$this->fields["position"]."` >= ".$position." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
$ref_ind = max($ref_ind, 1);
$self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
foreach($rchildren as $k => $v) {
if($v[$this->fields["position"]] - $self == $position) {
$ref_ind = (int)$v[$this->fields["left"]];
break;
}
}
if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
$ref_ind -= $ndif;
}
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $ref_node[$this->fields["owner"]]." AND `".$this->fields["left"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$sql[] = "" .
"UPDATE `".$this->table."` " .
"SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
"WHERE " .
"`".$this->fields["owner"]."` = ".(int) $ref_node[$this->fields["owner"]]." AND `".$this->fields["right"]."` >= ".$ref_ind." " .
( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
$ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
$idif = $ref_ind;
if($node !== false) {
$ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
$idif = $node[$this->fields["left"]] - $ref_ind;
if($is_copy) {
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."`" .
") " .
"SELECT " .
"".$ref_id.", " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
"`".$this->fields["level"]."` - (".$ldif.") " .
"FROM `".$this->table."` " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
"ORDER BY `".$this->fields["level"]."` ASC";
}
else {
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["parent_id"]."` = ".$ref_id.", " .
"`".$this->fields["position"]."` = ".$position." " .
"WHERE " .
"`".$this->fields["id"]."` = ".$id;
$sql[] = "" .
"UPDATE `".$this->table."` SET " .
"`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
"`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
"`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
"WHERE " .
"`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
}
} else {
$ewre = fSession::get('user[user_id]');
$sql[] = "" .
"INSERT INTO `".$this->table."` (" .
"`".$this->fields["owner"]."`, " .
"`".$this->fields["parent_id"]."`, " .
"`".$this->fields["position"]."`, " .
"`".$this->fields["left"]."`, " .
"`".$this->fields["right"]."`, " .
"`".$this->fields["level"]."` " .
") " .
"VALUES (" .
$ewre.", " .
$ref_id.", " .
$position.", " .
$idif.", " .
($idif + 1).", " .
$ldif.
")";
}
foreach($sql as $q) { $this->db->query($q); }
$ind = $this->db->insert_id();
if($is_copy) $this->_fix_copy($ind, $position);
return $node === false || $is_copy ? $ind : true;
}
}
Hope it helps someone...