Ver código fonte

sync code biall

Piotr Labudda 5 anos atrás
pai
commit
ba47dad432

+ 9 - 0
SE/index.php

@@ -28,6 +28,15 @@ require_once APP_PATH_ROOT . "/superedit-SEF.php";
 SEF('DEBUG_S');
 SEF('DEBUG_S');
 
 
 S::init();// init session variables if not exists
 S::init();// init session variables if not exists
+
+if ($defaultRoute = Config::get('DEFAULT_ROUTE')) {
+	$route = V::get('_route', '', $_REQUEST);
+	if (empty($route)) {
+		$_GET['_route'] = $defaultRoute;
+		$_REQUEST['_route'] = $defaultRoute;
+	}
+}
+
 User::auth();// die if not logged in
 User::auth();// die if not logged in
 
 
 if (!V::get('SKIP_TIMER', '', $_REQUEST)) S::timeoutUpdate(true);// User is authorized - update logout time
 if (!V::get('SKIP_TIMER', '', $_REQUEST)) S::timeoutUpdate(true);// User is authorized - update logout time

+ 1 - 1
SE/se-lib/App.php

@@ -362,7 +362,7 @@ class App {
 		if ($task = V::get('task', $default_task, $_GET)) {
 		if ($task = V::get('task', $default_task, $_GET)) {
 			$task_fun = 'task_'.$task;
 			$task_fun = 'task_'.$task;
 			if (function_exists($task_fun)) {
 			if (function_exists($task_fun)) {
-				echo "\n".'<div id="body_content">'."\n";
+				echo "\n".'<div id="body_content" p5-function="' . $task_fun . '">'."\n";
 					$task_fun();
 					$task_fun();
 				echo "\n".'</div>'."\n";
 				echo "\n".'</div>'."\n";
 			} else {
 			} else {

+ 22 - 1
SE/se-lib/Config.php

@@ -1,6 +1,10 @@
 <?php
 <?php
 /**
 /**
- * require define(APP_PATH_CONFIG)
+ * @require define(APP_PATH_CONFIG)
+ * @uses $_SERVER['SERVER_NAME']
+ * @uses ENV: P5_ACTIVE_PROJECT (.htaccess: SetEnv P5_ACTIVE_PROJECT kiosk -> saves in $_SERVER)
+ * @uses DB: `CRM_CONFIG` where CONF_KEY = 'activeProject'
+ * @uses FILE: APP_PATH_ROOT . DS . "projects" . DS . "{$activeProject}"
  *
  *
  * Config file name format:
  * Config file name format:
  ** po "-" zawsze $host ($_SERVER['SERVER_NAME']), inne "--"
  ** po "-" zawsze $host ($_SERVER['SERVER_NAME']), inne "--"
@@ -613,4 +617,21 @@ class Config {
 		return APP_PATH_ROOT . DS . "projects" . DS . "{$activeProject}";
 		return APP_PATH_ROOT . DS . "projects" . DS . "{$activeProject}";
 	}
 	}
 
 
+	public static function dbFetch($key, $defaultValue = null) {
+		$value = DB::getPDO()->fetchValue(" select CONF_VAL from CRM_CONFIG where CONF_KEY = :key ", [ ':key' => $key ]);
+		return (false === $value) ? $defaultValue : $value;
+	}
+	public static function dbUpdate($key, $value) {
+		return DB::getPDO()->insertOrUpdate('CRM_CONFIG', [
+			'CONF_KEY' => $key,
+			'@insert' => [
+				'CONF_VAL' => $value,
+			],
+			'@update' => [
+				'CONF_VAL' => $value,
+			]
+		]);
+	}
+
+
 }
 }

+ 8 - 8
SE/se-lib/Crypt.php

@@ -185,16 +185,16 @@ class Crypt {
 			$temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8);
 			$temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8);
 			$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
 			$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
 
 
-			$left = (($left << 1) | ($left >> 31 & $masks[31])); 
-			$right = (($right << 1) | ($right >> 31 & $masks[31])); 
+			$left = (($left << 1) | ($left >> 31 & $masks[31]));
+			$right = (($right << 1) | ($right >> 31 & $masks[31]));
 
 
 			//do this either 1 or 3 times for each chunk of the message
 			//do this either 1 or 3 times for each chunk of the message
 			for ($j=0; $j<$iterations; $j+=3) {
 			for ($j=0; $j<$iterations; $j+=3) {
 				$endloop = $looping[$j+1];
 				$endloop = $looping[$j+1];
 				$loopinc = $looping[$j+2];
 				$loopinc = $looping[$j+2];
-				//now go through and perform the encryption or decryption  
+				//now go through and perform the encryption or decryption
 				for ($i=$looping[$j]; $i!=$endloop; $i+=$loopinc) { //for efficiency
 				for ($i=$looping[$j]; $i!=$endloop; $i+=$loopinc) { //for efficiency
-					$right1 = $right ^ $keys[$i]; 
+					$right1 = $right ^ $keys[$i];
 					$right2 = (($right >> 4 & $masks[4]) | ($right << 28)) ^ $keys[$i+1];
 					$right2 = (($right >> 4 & $masks[4]) | ($right << 28)) ^ $keys[$i+1];
 					//the result is attained by passing these bytes through the S selection functions
 					//the result is attained by passing these bytes through the S selection functions
 					$temp = $left;
 					$temp = $left;
@@ -208,8 +208,8 @@ class Crypt {
 			} //for either 1 or 3 iterations
 			} //for either 1 or 3 iterations
 
 
 			//move then each one bit to the right
 			//move then each one bit to the right
-			$left = (($left >> 1 & $masks[1]) | ($left << 31)); 
-			$right = (($right >> 1 & $masks[1]) | ($right << 31)); 
+			$left = (($left >> 1 & $masks[1]) | ($left << 31));
+			$right = (($right >> 1 & $masks[1]) | ($right << 31));
 
 
 			//now perform IP-1, which is IP in the opposite direction
 			//now perform IP-1, which is IP in the opposite direction
 			$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
 			$temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1);
@@ -296,7 +296,7 @@ class Crypt {
 
 
 				//now apply PC-2, in such a way that E is easier when encrypting or decrypting
 				//now apply PC-2, in such a way that E is easier when encrypting or decrypting
 				//this conversion will look like PC-2 except only the last 6 bits of each byte are used
 				//this conversion will look like PC-2 except only the last 6 bits of each byte are used
-				//rather than 48 consecutive bits and the order of lines will be according to 
+				//rather than 48 consecutive bits and the order of lines will be according to
 				//how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
 				//how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
 				$lefttemp = $pc2bytes0[$left >> 28 & $masks[28]] | $pc2bytes1[($left >> 24 & $masks[24]) & 0xf]
 				$lefttemp = $pc2bytes0[$left >> 28 & $masks[28]] | $pc2bytes1[($left >> 24 & $masks[24]) & 0xf]
 								| $pc2bytes2[($left >> 20 & $masks[20]) & 0xf] | $pc2bytes3[($left >> 16 & $masks[16]) & 0xf]
 								| $pc2bytes2[($left >> 20 & $masks[20]) & 0xf] | $pc2bytes3[($left >> 16 & $masks[16]) & 0xf]
@@ -306,7 +306,7 @@ class Crypt {
 									| $pc2bytes9[($right >> 20 & $masks[20]) & 0xf] | $pc2bytes10[($right >> 16 & $masks[16]) & 0xf]
 									| $pc2bytes9[($right >> 20 & $masks[20]) & 0xf] | $pc2bytes10[($right >> 16 & $masks[16]) & 0xf]
 									| $pc2bytes11[($right >> 12 & $masks[12]) & 0xf] | $pc2bytes12[($right >> 8 & $masks[8]) & 0xf]
 									| $pc2bytes11[($right >> 12 & $masks[12]) & 0xf] | $pc2bytes12[($right >> 8 & $masks[8]) & 0xf]
 									| $pc2bytes13[($right >> 4 & $masks[4]) & 0xf];
 									| $pc2bytes13[($right >> 4 & $masks[4]) & 0xf];
-				$temp = (($righttemp >> 16 & $masks[16]) ^ $lefttemp) & 0x0000ffff; 
+				$temp = (($righttemp >> 16 & $masks[16]) ^ $lefttemp) & 0x0000ffff;
 				$keys[$n++] = $lefttemp ^ $temp; $keys[$n++] = $righttemp ^ ($temp << 16);
 				$keys[$n++] = $lefttemp ^ $temp; $keys[$n++] = $righttemp ^ ($temp << 16);
 			}
 			}
 		} //for each iterations
 		} //for each iterations

+ 1 - 1
SE/se-lib/FileUploader.php

@@ -845,7 +845,7 @@ class FileUploader {
 	public function makeDestFolder() {
 	public function makeDestFolder() {
 		$destFolderPath = $this->getDestLocalPath(true);
 		$destFolderPath = $this->getDestLocalPath(true);
 		$folderCreated = $this->tryCreateDestFolder($destFolderPath);
 		$folderCreated = $this->tryCreateDestFolder($destFolderPath);
-		if (!$folderCreated) throw new Exception("Nie udało się utworzyć katalogu");
+		if (!$folderCreated) throw new Exception("Nie udało się utworzyć katalogu");
 		$this->findFolder();
 		$this->findFolder();
 		return $this->getDestFolder();
 		return $this->getDestFolder();
 	}
 	}

+ 4 - 11
SE/se-lib/Route/Przypomnij.php

@@ -255,13 +255,6 @@ class Route_Przypomnij extends RouteBase {
 .fltr-hide_BRAK          tr.date-BRAK          {display:none;}
 .fltr-hide_BRAK          tr.date-BRAK          {display:none;}
 
 
 .nobr {white-space:nowrap;}
 .nobr {white-space:nowrap;}
-
-.btn-default { background-color:#fff; }
-.btn-default:hover { background-color:#fafafa; }
-.bejm_inactive_btn-default { background-color:#e8e8e8; color:#888; }
-.bejm_inactive_btn-default:hover { background-color:#e4ede4; color:#666;}
-.bejm_active { background-color:#e5ffe6/*#d8ffda-mocniej zielony*/; color:#222; /* border-top: 1px solid #00e62b; border-bottom: 1px solid #00e62b; */ }
-.bejm_active:hover { background-color:#dcf4dd; color:#666; /* border-top: 1px solid #00e62b; border-bottom: 1px solid #00e62b; */ }
 </style>
 </style>
 <div id="przypomnij-widget"></div>
 <div id="przypomnij-widget"></div>
 <script>
 <script>
@@ -583,14 +576,14 @@ class Route_Przypomnij extends RouteBase {
 			btnNode = $('<button class="btn btn-default" title="Filtr"><i class="glyphicon glyphicon-' + icon + '"></i></button>');
 			btnNode = $('<button class="btn btn-default" title="Filtr"><i class="glyphicon glyphicon-' + icon + '"></i></button>');
 			btnNode.appendTo(groupNode);
 			btnNode.appendTo(groupNode);
 			$.each(fltrItems, function(itemName, isActive) {
 			$.each(fltrItems, function(itemName, isActive) {
-				btnNode = $('<button class="btn btn-default bejm_inactive_btn-default"></button>');
+				btnNode = $('<button class="btn btn-default"></button>');
 				btnNode.data('type', fltrType);
 				btnNode.data('type', fltrType);
 				btnNode.data('name', itemName);
 				btnNode.data('name', itemName);
 				if (self.options.filters[fltrType]['itemTitles'][itemName]) {
 				if (self.options.filters[fltrType]['itemTitles'][itemName]) {
 					btnNode.attr('title', self.options.filters[fltrType]['itemTitles'][itemName]);
 					btnNode.attr('title', self.options.filters[fltrType]['itemTitles'][itemName]);
 				}
 				}
 				if (true === self._filters[fltrType][itemName]) {
 				if (true === self._filters[fltrType][itemName]) {
-					btnNode.addClass('bejm_active');
+					btnNode.addClass('active');
 				}
 				}
 				btnNode.text(self.options.filters[fltrType]['labels'][itemName]);
 				btnNode.text(self.options.filters[fltrType]['labels'][itemName]);
 				//btnNode.html(self.options.filters[fltrType]['labels'][itemName] + ' <span class="badge" style="background-color: #aaa;">3</span>');// TODO: TEST badge
 				//btnNode.html(self.options.filters[fltrType]['labels'][itemName] + ' <span class="badge" style="background-color: #aaa;">3</span>');// TODO: TEST badge
@@ -691,10 +684,10 @@ class Route_Przypomnij extends RouteBase {
 				}
 				}
 				var n = self._filterNodes[fltrType][itemName];
 				var n = self._filterNodes[fltrType][itemName];
 				if (isActive) {
 				if (isActive) {
-					n.addClass('bejm_active');
+					n.addClass('active');
 					self._tableNode.removeClass('fltr-hide_' + itemName);
 					self._tableNode.removeClass('fltr-hide_' + itemName);
 				} else {
 				} else {
-					n.removeClass('bejm_active');
+					n.removeClass('active');
 					self._tableNode.addClass('fltr-hide_' + itemName);
 					self._tableNode.addClass('fltr-hide_' + itemName);
 				}
 				}
 			});
 			});

+ 1 - 1
SE/se-lib/Route/ViewTableAjax.php

@@ -144,7 +144,7 @@ class Route_ViewTableAjax extends RouteBase {
 			$sibling = 'default_db/CRM_PROCES/PROCES_INIT'; DBG::nicePrint(array_merge(['type'=>"radio", 'name'=>"f_instance[{$sibling}]", 'value'=>'YES'], ('YES' === V::get($sibling, '', $filtrInstance)) ? ['checked' => "checked"] : []), "merge {$sibling} YES");
 			$sibling = 'default_db/CRM_PROCES/PROCES_INIT'; DBG::nicePrint(array_merge(['type'=>"radio", 'name'=>"f_instance[{$sibling}]", 'value'=>'YES'], ('YES' === V::get($sibling, '', $filtrInstance)) ? ['checked' => "checked"] : []), "merge {$sibling} YES");
 			$sibling = 'default_db/CRM_PROCES/PROCES_INIT'; DBG::nicePrint(array_merge(['type'=>"radio", 'name'=>"f_instance[{$sibling}]", 'value'=>'NO'], ('NO' === V::get($sibling, '', $filtrInstance)) ? ['checked' => "checked"] : []), "merge {$sibling} NO");
 			$sibling = 'default_db/CRM_PROCES/PROCES_INIT'; DBG::nicePrint(array_merge(['type'=>"radio", 'name'=>"f_instance[{$sibling}]", 'value'=>'NO'], ('NO' === V::get($sibling, '', $filtrInstance)) ? ['checked' => "checked"] : []), "merge {$sibling} NO");
 
 
-			$_ = array(UI, 'h');
+			$_ = [ 'UI', 'h' ];
 			echo $_('form', ['method' => "POST", 'style' => "width:600px; border:1px solid #ddd; border-radius:2px"], [
 			echo $_('form', ['method' => "POST", 'style' => "width:600px; border:1px solid #ddd; border-radius:2px"], [
 				$_('div', ['style' => "background-color:#ddd"], "Test Filtr instancji"),
 				$_('div', ['style' => "background-color:#ddd"], "Test Filtr instancji"),
 				$_('div', ['style' => "padding:8px"], array_map(function ($sibling) use ($filtrInstance, $_) {
 				$_('div', ['style' => "padding:8px"], array_map(function ($sibling) use ($filtrInstance, $_) {

+ 30 - 3
SE/se-lib/RouteBase.php

@@ -1,9 +1,36 @@
 <?php
 <?php
 
 
 Lib::loadClass('UI');
 Lib::loadClass('UI');
+Lib::loadClass('Router');
+Lib::loadClass('Request');
 
 
 class RouteBase {
 class RouteBase {
 
 
+	public $_label = '';
+
+	public function getLabel() {
+		if ($this->_label) return $this->_label;
+		$clsName = get_class($this);
+		if ('Route_' != substr($clsName, 0, strlen('Route_'))) throw new Exception("Wrong route class name '{$clsName}' - expecpted 'Route_' prefix");
+		$this->_label = substr($clsName, strlen('Route_'));
+		return $this->_label;
+	}
+	public function viewBackUrlsContainer() {
+		UI::startContainer();
+		echo UI::h('a', ['style'=>"margin:8px", 'class'=>"btn btn-xs btn-default", 'href'=>$this->getLink()], "wróć do " . $this->getLabel());
+		$referRoute = Request::getRefererRoute();
+		if ($referRoute) echo UI::h('a', ['style'=>"margin:8px", 'class'=>"btn btn-xs btn-default", 'href'=>Router::getRoute($referRoute)->getLink()], "wróć do " . Router::getRoute($referRoute)->getLabel());
+		UI::endContainer();
+	}
+
+	public function __construct() {
+		$this->_init();
+	}
+
+	public function _init() {
+		// add init variables
+	}
+
 	public function route() {
 	public function route() {
 		$task = V::get('_task', '', $_REQUEST);
 		$task = V::get('_task', '', $_REQUEST);
 		if (empty($task)) {
 		if (empty($task)) {
@@ -69,13 +96,13 @@ class RouteBase {
 		throw new Exception("Not Implemented args type", 501);
 		throw new Exception("Not Implemented args type", 501);
 	}
 	}
 
 
-	public function runTask($task) {
-		if (empty($task)) throw new Exception("Empty method name");
+	public function runTask($task, $args = []) {
+		$task = V::getValue($task, 'default');
 		$methodName = "{$task}Action";
 		$methodName = "{$task}Action";
 		if (!method_exists($this, $methodName)) {
 		if (!method_exists($this, $methodName)) {
 			throw new Exception("Task '{$task}' not exists");
 			throw new Exception("Task '{$task}' not exists");
 		}
 		}
-		$this->{$methodName}();
+		$this->{$methodName}($args);
 	}
 	}
 
 
 	public function runMethod($methodName) {
 	public function runMethod($methodName) {

+ 1 - 1
SE/se-lib/S.php

@@ -124,7 +124,7 @@ class S {
 
 
 		UI::inlineJS( __FILE__ . ".sessionTimer.js", [
 		UI::inlineJS( __FILE__ . ".sessionTimer.js", [
 			'BASE_URL' => Request::getPathUri(),
 			'BASE_URL' => Request::getPathUri(),
-			'USER_SESSION_EXPIRE' => $_SESSION['USER_SESSION_EXPIRE'],
+			'USER_SESSION_EXPIRE' => V::get('USER_SESSION_EXPIRE', 0, $_SESSION, 'int'),
 			'SESSION_TIMER_URL' => "session-expire.php?task=getTimer",
 			'SESSION_TIMER_URL' => "session-expire.php?task=getTimer",
 			'SESSION_AUTH_STATUS_URL' => "session-expire.php?task=getAuthStatus",
 			'SESSION_AUTH_STATUS_URL' => "session-expire.php?task=getAuthStatus",
 			'USER_LOGIN' => User::getLogin(),
 			'USER_LOGIN' => User::getLogin(),

+ 1 - 1
SE/se-lib/TableAjax.php

@@ -271,7 +271,7 @@ class TableAjax extends ViewAjax {
 		echo UI::h('link', ['rel'=>"stylesheet", 'type'=>"text/css", 'href'=>"static/sweetalert2.min.css"]);
 		echo UI::h('link', ['rel'=>"stylesheet", 'type'=>"text/css", 'href'=>"static/sweetalert2.min.css"]);
 		UI::inlineCSS( __FILE__ . '.style.css' );
 		UI::inlineCSS( __FILE__ . '.style.css' );
 		echo UI::h('script', [ 'src' => "static/vendor.js" ]); // window.p5VendorJs: {React, ReactDOM, createReactClass, Redux}
 		echo UI::h('script', [ 'src' => "static/vendor.js" ]); // window.p5VendorJs: {React, ReactDOM, createReactClass, Redux}
-		echo UI::h('script', [ 'src' => "static/p5UI/buildDom.js" ]);
+		echo UI::h('script', [ 'src' => "static/p5UI/buildDom.js" ]); // p5UI__buildDom
 		$_rendered = true;
 		$_rendered = true;
 	}
 	}
 
 

+ 2 - 2
SE/se-lib/TableAjax.php.createTableSelectedStateObject.js

@@ -295,10 +295,10 @@ function selectedActions(idContext) {
 }
 }
 
 
 function createTableSelectedStateObject(idContext) {
 function createTableSelectedStateObject(idContext) {
-	var _idContext = idContext || {};
+	var _idContext = idContext || 0;
 	return {
 	return {
 		store: createStoreWithThunkMiddleware(selectedStore),
 		store: createStoreWithThunkMiddleware(selectedStore),
-		actions: selectedActions(_idContext)
+		actions: selectedActions(_idContext),
 	}
 	}
 }
 }
 
 

+ 26 - 0
SE/se-lib/UserAcl.php

@@ -179,6 +179,32 @@ class UserAcl {
 		} else if ('default_db__x3A__' == substr($sourceName, 0, 17)) {
 		} else if ('default_db__x3A__' == substr($sourceName, 0, 17)) {
 			$rootTableName = strtolower(substr($sourceName, 17));
 			$rootTableName = strtolower(substr($sourceName, 17));
 			return SchemaFactory::loadTableObject($rootTableName, $objName);
 			return SchemaFactory::loadTableObject($rootTableName, $objName);
+		} else if ('zasob_' == substr($sourceName, 0, strlen('zasob_'))) {
+			$idDatabase = strtolower(substr($sourceName, strlen('zasob_')));
+			// return SchemaFactory::loadTableObject($rootTableName, $objName);
+			if (!is_numeric($idDatabase)) throw new HttpException("Not Implemented - Database({$idDatabase})", 501);
+			$remoteDB = DB::getPDO($idDatabase); // TODO: may throw Exception 'Config file not exists ...'
+			DBG::log($remoteDB, 'array', "\$remoteDB");
+			$dbType = $remoteDB->getType();
+			switch ($dbType) {
+				case 'mysql': {
+					// throw new HttpException("Not Implemented - TODO idDatabase({$idDatabase}) type({$dbType})", 501);
+					$zasobTblInfo = ProcesHelper::getZasobTableInfoByUri("{$sourceName}/{$objName}");
+					DBG::log($zasobTblInfo, 'array', "\$zasobTblInfo");
+					if (!$zasobTblInfo) throw new HttpException("Object not Found '{$objName}'", 404);
+					if (!$this->hasTableAcl($zasobTblInfo->ID)) throw new HttpException("Access Denied for '{$sourceName}/{$objName}'", 403);
+					return $this->getTableAcl($zasobTblInfo->ID);
+				}
+				case 'pgsql': {
+					$zasobTblInfo = ProcesHelper::getZasobTableInfoByUri("{$sourceName}/{$objName}");
+					DBG::log($zasobTblInfo, 'array', "\$zasobTblInfo");
+					if (!$zasobTblInfo) throw new HttpException("Object not Found '{$objName}'", 404);
+					if (!$this->hasTableAcl($zasobTblInfo->ID)) throw new HttpException("Access Denied for '{$sourceName}/{$objName}'", 403);
+					return $this->getTableAcl($zasobTblInfo->ID);
+					// throw new HttpException("Not Implemented - TODO idDatabase({$idDatabase}) type({$dbType})", 501);
+				}
+				default: throw new HttpException("Not Implemented - TODO idDatabase({$idDatabase}) type({$dbType})", 501);
+			}
 		}
 		}
 		throw new HttpException("Not Implemented", 501);
 		throw new HttpException("Not Implemented", 501);
 	}
 	}

+ 15 - 0
SE/se-lib/V.php

@@ -253,6 +253,21 @@ class V {
 		}
 		}
 	}
 	}
 
 
+	static function safePrintPrettyJson($json) {
+		if (empty($json)) return '{}';
+		try {
+			$decoded = json_decode($json);
+			if (NULL === $decoded) {
+				throw new Exception(json_last_error());
+			}
+			return json_encode($decoded, $options = JSON_PRETTY_PRINT);
+		} catch (Exception $e) {
+			DBG::log($e);
+			return 'JSON DECODE ERROR: ' . $e->getMessage();
+		}
+	}
+
+
 	public static function copy($o) {
 	public static function copy($o) {
 		$null = null;
 		$null = null;
 		if (!$o) {
 		if (!$o) {