Subversion Repositories oidplus

Rev

Rev 20 | Rev 28 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. abstract class OIDplusObject {
  21.         public static $registeredObjectTypes = array();
  22.  
  23.         public static function parse($node_id) { // please overwrite this function!
  24.                 // TODO: in case we are not calling this class directly, check if function is overwritten and throw exception otherwise
  25.                 foreach (self::$registeredObjectTypes as $ot) {
  26.                         if ($obj = $ot::parse($node_id)) return $obj;
  27.                 }
  28.                 return null;
  29.         }
  30.  
  31.         public abstract static function objectTypeTitle();
  32.  
  33.         public abstract static function objectTypeTitleShort();
  34.  
  35.         public abstract static function ns();
  36.  
  37.         public abstract static function root();
  38.  
  39.         public abstract function isRoot();
  40.  
  41.         public abstract function nodeId();
  42.  
  43.         public abstract function addString($str);
  44.  
  45.         public abstract function crudShowId(OIDplusObject $parent);
  46.  
  47.         public abstract function crudInsertPrefix();
  48.  
  49.         public abstract function jsTreeNodeName(OIDplusObject $parent = null);
  50.  
  51.         public abstract function defaultTitle();
  52.  
  53.         public abstract function isLeafNode();
  54.  
  55.         public abstract function getContentPage(&$title, &$content);
  56.  
  57.         public static function getRaRoots($ra_email=null) {
  58.                 $out = array();
  59.                 if (is_null($ra_email)) {
  60.                         $res = OIDplus::db()->query("select oChild.id as id, oChild.ra_email as child_mail, oParent.ra_email as parent_mail from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
  61.                                                     "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
  62.                                                     "order by ".OIDplus::db()->natOrder('oChild.id'));
  63.                         while ($row = OIDplus::db()->fetch_array($res)) {
  64.                                 if (!OIDplus::authUtils()::isRaLoggedIn($row['parent_mail']) && OIDplus::authUtils()::isRaLoggedIn($row['child_mail'])) {
  65.                                         $out[] = self::parse($row['id']);
  66.                                 }
  67.                         }
  68.                 } else {
  69.                         $res = OIDplus::db()->query("select oChild.id as id from ".OIDPLUS_TABLENAME_PREFIX."objects as oChild ".
  70.                                                     "left join ".OIDPLUS_TABLENAME_PREFIX."objects as oParent on oChild.parent = oParent.id ".
  71.                                                     "where ifnull(oParent.ra_email,'') <> '".OIDplus::db()->real_escape_string($ra_email)."' and oChild.ra_email = '".OIDplus::db()->real_escape_string($ra_email)."' ".
  72.                                                     "order by ".OIDplus::db()->natOrder('oChild.id'));
  73.                         while ($row = OIDplus::db()->fetch_array($res)) {
  74.                                 $out[] = self::parse($row['id']);
  75.                         }
  76.                 }
  77.                 return $out;
  78.         }
  79.  
  80.         private static function getAllNonConfidential_rec($parent=null, &$out) {
  81.                 if (is_null($parent)) {
  82.                         $roots = array();
  83.                         foreach (self::$registeredObjectTypes as $ot) {
  84.                                 $roots[] = "parent = '" . OIDplus::db()->real_escape_string($ot::root()) . "'";
  85.                         }
  86.                         $roots = implode(' or ', $roots);
  87.                 } else {
  88.                         $roots = "parent = '" . OIDplus::db()->real_escape_string($parent) . "'";
  89.                 }
  90.  
  91.                 $res = OIDplus::db()->query("select id, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where $roots order by ".OIDplus::db()->natOrder('id'));
  92.  
  93.                 while ($row = OIDplus::db()->fetch_array($res)) {
  94.                         if ($row['confidential'] == '1') {
  95.                                 // do nothing
  96.                         } else {
  97.                                 $out[] = $row['id'];
  98.                                 self::getAllNonConfidential_rec($row['id'], $out);
  99.                         }
  100.                 }
  101.         }
  102.  
  103.         public static function getAllNonConfidential() {
  104.                 $out = array();
  105.                 self::getAllNonConfidential_rec(null, $out);
  106.                 return $out;
  107.         }
  108.  
  109.         public function isConfidential() {
  110.                 $curid = $this->nodeId();
  111.                 // Recursively search for the confidential flag in the parents
  112.                 while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent, confidential from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
  113.                         $row = OIDplus::db()->fetch_array($res);
  114.                         if ($row['confidential']) return true;
  115.                         $curid = $row['parent'];
  116.                 }
  117.  
  118.                 return false;
  119.         }
  120.  
  121.         public function isChildOf(OIDplusObject $obj) {
  122.                 $curid = $this->nodeId();
  123.                 while (OIDplus::db()->num_rows($res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($curid)."'")) > 0) {
  124.                         $row = OIDplus::db()->fetch_array($res);
  125.                         if ($curid == $obj->nodeId()) return true;
  126.                         $curid = $row['parent'];
  127.                 }
  128.  
  129.                 return false;
  130.         }
  131.  
  132.         public function userHasReadRights($ra_email=null) {
  133.                 // Admin may do everything
  134.                 if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  135.  
  136.                 // If it is not confidential, everybody can read/see it.
  137.                 if (!$this->isConfidential()) return true;
  138.  
  139.                 // If we own the object, we may see it
  140.                 if (is_null($ra_email)) {
  141.                         if ($this->userHasWriteRights()) return true;
  142.                 } else {
  143.                         $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  144.                         $row = OIDplus::db()->fetch_array($res);
  145.                         if ($row['ra_email'] == $ra_email) return true;
  146.                 }
  147.  
  148.                 // If someone has rights to an object below our confidential node,
  149.                 // we let him see the confidential node,
  150.                 // Otherwise he could not browse through to his own node.
  151.                 $roots = $this->getRaRoots($ra_email);
  152.                 foreach ($roots as $root) {
  153.                         if ($root->isChildOf($this)) return true;
  154.                 }
  155.  
  156.                 return false;
  157.         }
  158.  
  159.         public function getIcon($row=null) {
  160.                 $namespace = $this->ns(); // must use $this, not self::, otherwise the virtual method will not be called
  161.  
  162.                 if (is_null($row)) {
  163.                         $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  164.                         $row = OIDplus::db()->fetch_array($res);
  165.                 }
  166.                 // TODO: have different icons for Leaf-Nodes
  167.                 if (OIDplus::authUtils()::isRaLoggedIn($row['ra_email'])) {
  168.                         $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_own.png';
  169.                 } else {
  170.                         $icon = 'plugins/objectTypes/'.$namespace.'/img/treeicon_general.png';
  171.                 }
  172.                 if (!file_exists($icon)) $icon = null; // default icon (folder)
  173.                 return $icon;
  174.         }
  175.  
  176.         public static function exists($id) {
  177.                 $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($id)."'");
  178.                 return OIDplus::db()->num_rows($res) > 0;
  179.         }
  180.  
  181.         public function getParent() {
  182.                 $res = OIDplus::db()->query("select parent from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  183.                 $row = OIDplus::db()->fetch_array($res);
  184.                 $parent = $row['parent'];
  185.                 $obj = OIDplusObject::parse($parent);
  186.                 if ($obj) return $obj;
  187.  
  188.                 // If this OID does not exist, the SQL query "select parent from ..." does not work. So we try to find the next possible parent using one_up()
  189.                 $cur = $this->one_up();
  190.                 if (!$cur) return false;
  191.                 do {
  192.                         if ($fitting = self::findFitting($cur->nodeId())) return $fitting;
  193.  
  194.                         $prev = $cur;
  195.                         $cur = $cur->one_up();
  196.                         if (!$cur) return false;
  197.                 } while ($prev != $cur);
  198.  
  199.                 return false;
  200.         }
  201.  
  202.         public function getRaMail() {
  203.                 $res = OIDplus::db()->query("select ra_email from ".OIDPLUS_TABLENAME_PREFIX."objects where id = '".OIDplus::db()->real_escape_string($this->nodeId())."'");
  204.                 $row = OIDplus::db()->fetch_array($res);
  205.                 return $row['ra_email'];
  206.         }
  207.  
  208.         public function userHasParentalWriteRights($ra_email=null) {
  209.                 if (is_null($ra_email)) {
  210.                         if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  211.                 }
  212.  
  213.                 $objParent = $this->getParent();
  214.                 if (is_null($objParent)) return false;
  215.                 return $objParent->userHasWriteRights($ra_email);
  216.         }
  217.  
  218.         public function userHasWriteRights($ra_email=null) {
  219.                 if (is_null($ra_email)) {
  220.                         if (OIDplus::authUtils()::isAdminLoggedIn()) return true;
  221.                         return OIDplus::authUtils()::isRaLoggedIn($this->getRaMail());
  222.                 } else {
  223.                         return $this->getRaMail() == $ra_email;
  224.                 }
  225.         }
  226.  
  227.         public function distance($to) {
  228.                 return null; // not implemented
  229.         }
  230.  
  231.         public function equals($obj) {
  232.                 if (!is_object($obj)) $obj = OIDplusObject::parse($obj);
  233.                 $distance = $this->distance($obj);
  234.                 if (is_numeric($distance)) return $distance === 0; // if the distance function is implemented, use it
  235.  
  236.                 return $this->nodeId() == $obj->nodeId(); // otherwise compare the node id case-sensitive
  237.         }
  238.  
  239.         public static function findFitting($id) {
  240.                 $obj = OIDplusObject::parse($id);
  241.                 if (!$obj) throw new Exception("findFitting: Parse failed\n");
  242.  
  243.                 $res = OIDplus::db()->query("select * from ".OIDPLUS_TABLENAME_PREFIX."objects where id like '".OIDplus::db()->real_escape_string($obj->ns()).":%'");
  244.                 while ($row = OIDplus::db()->fetch_object($res)) {
  245.                         $test = OIDplusObject::parse($row->id);
  246.                         if ($obj->equals($test)) return $test;
  247.                 }
  248.                 return false;
  249.         }
  250.  
  251.         public function one_up() {
  252.                 return null; // not implemented
  253.         }
  254. }
  255.