function get_open_gates($gate, $pregates = array()) { $inherits = $GLOBALS['inherit_code'][$gate]; if (!empty($inherits)) { foreach ($inherits as $tmpgate) { if (!in_array($tmpgate, $pregates)) { array_push($pregates, $tmpgate); } $pregates = get_open_gates($tmpgate, $pregates); } } return $pregates; }
function top_down_propagation_list($toFind, $root, $db, $Hlist = array(), $all_datafile = '', $all_sharedfile = '', $j = 0) { global $timer; $n = 5; #top down propagation list finds the children, and the children's children , of the parents indicated in root. Propagation stops when the core element that is being seeked (toFInd) is reached. if (is_file($Hlist)) { $Hlist = unserialize(file_get_contents($Hlist)); } if (is_file($all_data_file)) { $all_data = unserialize(file_get_contents($all_data_file)); unlink($all_data_file); } if (is_file($all_sharedfile)) { $all_shared = unserialize(file_get_contents($all_sharedfile)); unlink($all_sharedfile); } if (!is_array($root)) { $root = array($root); } $e = letter($toFind); $e_upstream = get_open_gates($e); #how many of the root are of the same kind? (that is, if $letters = array(); foreach ($root as $p) { $l = letter($p); if (empty($letters[$l])) { $letters[$l] = 0; $parent_uid[$l] = array(); } $letters[$l]++; array_push($parent_uid[$l], $p); } #for those that have + 10 elements and belong to the $e_upstream (that is, are open gates in the flood), search for every downstream element regardelss of parent id foreach ($letters as $pl => $p_times) { #these must be declared in order to find the correct parent id $p_element = $GLOBALS['s3codes'][$pl]; $p_element_idname = $GLOBALS['COREids'][$p_element]; $next_tables = $GLOBALS['next_element'][$pl]; if (is_array($next_tables)) { foreach ($next_tables as $tC) { #qhery this only if this table has not been queried yet; since one row may contain several parents ((for example, a rule inherits from a project but also form the subject collection if (in_array($tC, $e_upstream) || $tC == $e) { if (!is_array($all_data[$tC])) { $element = $GLOBALS['s3codes'][$tC]; $tn = $GLOBALS['s3tables'][$GLOBALS['s3codes'][$tC]]; $tn_id = $GLOBALS['s3ids'][$element]; #beause collection and item are in the same table, this correction is needed; replace collection_id with "resource_class_id" in the query $parent_id = $GLOBALS['s3map'][$GLOBALS['plurals'][$element]][$p_element_idname] != '' ? $GLOBALS['s3map'][$GLOBALS['plurals'][$element]][$p_element_idname] : $p_element_idname; #retrieve all elements of this time from the table $sql = "select * from s3db_" . $tn . ""; $connector = "where"; if ($tC == 'I') { $sql .= " " . $connector . " iid='1'"; $connector = "and"; } if ($tC == 'C') { $sql .= " " . $connector . " iid='0'"; $connector = "and"; } if ($tC == 'R') { $sql .= " " . $connector . " object!='UID'"; $connector = "and"; } #if there are very few propagation points from this letter, reduce the query to only those - building Hlist will be much faster this way if ($p_times < $n) { foreach ($parent_uid[$pl] as $tmp) { $id_value = ereg_replace(letter($tmp), '', $tmp); if ($tC == 'R' && $pl == 'I') { #when tC is R, it migrates from C and I, but let's not go through it at this point because it takes too long; query bottom up at the subject_id,verb_id,object_id level may be faster #I know something is wrong with this query to reduce the data, but i don't know waht... problem is that the collections that show up here are only those where user has direct assigned permssion, not the ones that migrate from the project #$sql .= " ".$connector." ((subject_id = '".$id_value."') or (object_id = '".$id_value."')) "; } else { $sql .= " " . $connector . " (" . $parent_id . " = '" . $id_value . "') "; } $connector = "or"; } } $db->query($sql); if ($timer) { $timer->setMarker('entity query run: ' . $sql); } while ($db->next_record()) { $cols = $GLOBALS['dbstruct'][$GLOBALS['plurals'][$element]]; $uid = $tC . $db->f($tn_id); for ($i = 0; $i < count($cols); $i++) { $all_data[$tC][$uid][$cols[$i]] = $db->f($cols[$i]); } } } #also look for children of this p in the permissions table if (!is_array($all_shared[$pl . $tC])) { if ($tC == 'R' && ($pl == 'C' || $pl == 'I')) { #bypass to do bbottom up #echo 'ola';exit; } else { $sqlP = "select shared_with,uid from s3db_permission "; $connector = "where"; if ($p_times < $n) { foreach ($parent_uid[$pl] as $tmp) { $sqlP .= $connector . " (shared_with = '" . $tmp . "') "; $connector = "or"; } $connector = "and"; } else { $sqlP .= $connector . " shared_with " . $GLOBALS['regexp'] . " '^" . $pl . "'"; $connector = "and"; } $sqlP .= " " . $connector . " uid " . $GLOBALS['regexp'] . " '^" . $tC . "'"; $sqlP .= " " . $connector . " id not in (" . str_replace("*", $tn_id, $sql) . ")"; $db->query($sqlP); if ($timer) { $timer->setMarker('permission query run: ' . $sqlP); } #Since there can only be 1 uid, 1shared_with per row, we can build Hlist right away while ($db->next_record()) { $uid = $db->f('uid'); $sw = $db->f('shared_with'); #save the data found for general queries if ($p_times > $n) { $all_shared[$pl . $tC][$sw] = $uid; } else { if (strlen($sw) > 1) { if (!is_array($Hlist[$sw])) { $Hlist[$sw] = array(); } if (!in_array($uid, $Hlist[$sw])) { array_push($Hlist[$sw], $uid); $moreC[] = $uid; } } } } } } #now distribute the all shared across parent/child connectors if (is_array($all_shared[$pl . $tC])) { foreach ($all_shared[$pl . $tC] as $sw => $uid) { if (strlen($sw) >= 1) { if (!is_array($Hlist[$sw])) { $Hlist[$sw] = array(); } if (!in_array($uid, $Hlist[$sw])) { if (in_array(letter($uid), $e_upstream)) { array_push($Hlist[$sw], $uid); $moreC[] = $uid; } } } } } #now redistribute all_data according to the parent being explored if (is_array($all_data[$tC])) { foreach ($all_data[$tC] as $uid => $element_info) { ##a little trick to asusme subject-Id and object_id as collections; verb_id as items; if ($tC == 'R') { if ($pl == 'C') { $sw = $pl . $element_info['subject_id']; } if ($pl == 'I') { $sw = $pl . $element_info['verb_id']; } } else { $sw = $pl . $element_info[$parent_id]; } #when there is not data for parent (for example, object_id is empty), there is not need to propagate if (strlen($sw) > 1) { if (!is_array($Hlist[$sw])) { $Hlist[$sw] = array(); } if (!in_array($uid, $Hlist[$sw])) { array_push($Hlist[$sw], $uid); #is there child data for this element yet? #if(!($e=='R' && !ereg('^S',$uid))) #because there can be some many items, and rule query should be fast, will not propagate from I to rule, for now... if (in_array(letter($uid), $e_upstream)) { $moreC[] = $uid; } } } } } } } } #if all entities were queries, put data in a file to save time next time (but not if only a subset was queried => TO BE COMPLETED #And now build the seed that will be used to propagate permissions to the next level if (!empty($moreC)) { $all_data_file = $GLOBALS['uploads'] . 'alldata_tmp' . rand(100, 200); file_put_contents($all_data_file, serialize($all_data)); if ($timer) { $timer->setMarker('Saving data in a file.'); } #save the var in disk $Hlist_file = $GLOBALS['uploads'] . 'Hlist' . rand(100, 200); file_put_contents($Hlist_file, serialize($Hlist)); chmod($Hlist_file, 0777); #save the shared $shared_file = $GLOBALS['uploads'] . 'shared' . rand(100, 200); file_put_contents($shared_file, serialize($all_shared)); chmod($shared_file, 0777); $j++; $Hlist = top_down_propagation_list($toFind, $moreC, $db, $Hlist_file, $all_data_file, $shared_file, $j); } } return $Hlist; }