public function testTimeGetCurrentGMT(){
		$ref = new DateTime(null, new DateTimeZone('UTC'));

		$this->assertEquals($ref->format('U'), \Time::GetCurrentGMT('U'));

		$this->assertEquals($ref->format('Y-m-d'), \Time::GetCurrentGMT('Y-m-d'));
	}
 public function set($k, $v)
 {
     switch ($k) {
         case 'status':
             // Update the published date if it's status has changed.
             if ($v == $this->get($k)) {
                 return false;
             }
             if ($v == 'published' && !$this->get('published')) {
                 parent::set('published', Time::GetCurrentGMT());
             } elseif ($v == 'draft' && $this->get('published')) {
                 parent::set('published', '');
             }
             // And resume!
             return parent::set($k, $v);
         case 'published':
             // make sure this is a valid timestamp!
             if ($v != '' && !is_numeric($v)) {
                 $time = strtotime($v);
                 return parent::set($k, $time);
             } else {
                 return parent::set($k, $v);
             }
         default:
             return parent::set($k, $v);
     }
 }
	$md5 = md5_file($dirname . $fname);

	$allfiles[] = array(
		'file' => $fname,
		'md5' => $md5,
		'controllers' => array($class . 'Controller')
	);

	// Don't forget to create a template directory for any pages on this controller.
	$dir = new \Core\Filestore\Backends\DirectoryLocal($dirname . 'templates/pages/' . strtolower($class));
	$dir->mkdir();
}


// Write the changelog
$now = Time::GetCurrentGMT(Time::FORMAT_RFC2822);
file_put_contents($dirname . 'CHANGELOG', "$componentname 1.0.0

	* Initial version

");
$allfiles[] = array(
	'file' => 'CHANGELOG',
	'md5' => md5_file($dirname . 'CHANGELOG')
);

// And the readme
file_put_contents($dirname . 'README.md', "# About $componentname

@todo Write something about this component.
");
Beispiel #4
0
	/**
	 * Delete this record from the datastore.
	 *
	 * Will IMMEDIATELY remove the record!
	 *
	 * If this model has a "deleted" column that is set as a zero value, that record is set to the current timestamp instead.
	 * This functionality is meant for advanced record tracking such as those in use in sync systems.
	 *
	 * @return bool
	 * @throws Exception
	 */
	public function delete() {

		$classname = get_called_class();
		// Allow all supplemental models to tap into this too!
		if(isset(self::$_ModelSupplementals[$classname])){
			foreach(self::$_ModelSupplementals[$classname] as $supplemental){
				if(class_exists($supplemental)){
					$ref = new ReflectionClass($supplemental);
					if($ref->hasMethod('PreDeleteHook')){
						$ref->getMethod('PreDeleteHook')->invoke(null, $this);
					}
				}
			}
		}

		foreach ($this->_columns as $c) {
			/** @var \Core\Datamodel\Columns\SchemaColumn $c */
			
			// Certain key types have certain functions.
			if($c->type == Model::ATT_TYPE_DELETED) {
				// Is this record already set as deleted?
				// If it is, then proceed with the delete as usual.
				// Otherwise, update the record instead of deleting it.
				if(!$c->value){
					$nv = Time::GetCurrentGMT();
					$this->set($c->field, $nv);
					return $this->save();
				}
				else{
					// I can safely break out of the foreach statement at this stage.
					break;
				}
			}
		}

		// Blank out any dependent records based on links.
		// Since relationships may have various levels, I need to execute delete on each of them instead of just
		// issuing a broad delete request.
		foreach ($this->_linked as $k => $l) {

			switch($l['link']){
				case Model::LINK_HASONE:
					// Delete this child, (and any of its subordinates).
					$child = $this->getLink($k);
					$child->delete();
					break;
				case Model::LINK_HASMANY:
					// Request all the children and issue a delete on them.
					$children = $this->getLink($k);
					foreach($children as $child){
						/** @var Model $child */
						$child->delete();
					}
					break;
				// There is no default behaviour... other than to ignore it.
			}

			if (isset($this->_linked[$k]['records'])) unset($this->_linked[$k]['records']);
		}


		if ($this->exists()) {

			// Check and see if this model extends another model.
			// If it does, then create/update that parent object to keep it in sync!
			if(($class = get_parent_class($this)) != 'Model'){
				$idx = self::GetIndexes();
				if(isset($idx['primary']) && sizeof($idx['primary']) == 1){
					$schema = $this->getKeySchema($idx['primary'][0]);
					if($schema['type'] == Model::ATT_TYPE_UUID){
						$refp = new ReflectionClass($class);
						$refm = $refp->getMethod('Construct');
						/** @var Model $parent */
						$parent = $refm->invoke(null, $this->get($idx['primary'][0]));
						$parent->delete();
					}
				}
			}

			$n = $this->_getTableName();
			$i = self::GetIndexes();
			// Delete the data from the database.
			$dat = new Core\Datamodel\Dataset();

			$dat->table($n);

			if (!isset($i['primary'])) {
				throw new Exception('Unable to delete model [ ' . get_class($this) . ' ] without any primary keys.');
			}

			$pri = $i['primary'];
			if(!is_array($pri)) $pri = [$pri];

			foreach ($pri as $k) {
				$dat->where([$k => $this->get($k)]);
			}

			$dat->limit(1)->delete();

			if ($dat->execute($this->interface)) {
				$this->_exists = false;
			}
		}

		return true;
	}
	/**
	 * Cleanup any expired sessions from the database.
	 *
	 * @return bool Always returns true :)
	 */
	public static function CleanupExpired(){
		static $lastexecuted = 0;

		/**
		 * Delete ANY session that has expired.
		 */
		$ttl = \ConfigHandler::Get('/core/session/ttl');
		$datetime = (\Time::GetCurrentGMT() - $ttl);

		if($lastexecuted == $datetime){
			// This operation was already called this second.  No need to do it again.
			// This is used because if a LOT of user operations occur on a given page,
			// this method may be called many many many times.
			return true;
		}

		// Low-level datasets are used here because they have less overhead than
		// the full-blown model system.
		$dataset = new Datamodel\Dataset();
		$dataset->table('session');
		$dataset->where('updated < ' . $datetime);
		$dataset->delete()->execute();

		$lastexecuted = $datetime;

		// Always return TRUE
		return true;
	}
 /**
  * Execute the actual cron for the requested type.
  *
  * @param string $cron Cron type to execute.
  *
  * @return CronLogModel
  * @throws Exception
  */
 private function _performcron($cron)
 {
     switch ($cron) {
         case '1-minute':
         case '5-minute':
         case '15-minute':
         case '30-minute':
         case 'hourly':
         case '2-hour':
         case '3-hour':
         case '6-hour':
         case '12-hour':
         case 'daily':
         case 'weekly':
         case 'monthly':
             break;
         default:
             throw new Exception('Unsupported cron type: [' . $cron . ']');
     }
     if (!ConfigHandler::Get('/cron/enabled')) {
         $msg = 'Cron execution is globally disabled via the site configuration, not executing cron!';
         SystemLogModel::LogInfoEvent('/cron/' . $cron, $msg);
         // It needs to return something.
         $log = new CronLogModel();
         $log->set('status', 'fail');
         return $log;
     }
     // First, check and see if there's one that's still running.
     $runninglogs = CronLogModel::Find(array('cron' => $cron, 'status' => 'running'));
     if (sizeof($runninglogs)) {
         foreach ($runninglogs as $log) {
             /** @var $log CronLogModel */
             $log->set('status', 'fail');
             $log->set('log', $log->get('log') . "\n------------\nTIMED OUT!");
             $log->save();
         }
     }
     // Start recording.
     $log = new CronLogModel();
     $log->set('cron', $cron);
     $log->set('status', 'running');
     $log->set('memory', memory_get_usage());
     $log->set('ip', REMOTE_IP);
     $log->save();
     $start = microtime(true) * 1000;
     $sep = '==========================================' . "\n";
     $contents = "Starting cron execution for {$cron}\n{$sep}";
     // This uses the hook system, but will be slightly different than most things.
     $overallresult = true;
     $hook = HookHandler::GetHook('/cron/' . $cron);
     $hookcount = 0;
     $hooksuccesses = 0;
     if ($hook) {
         if ($hook->getBindingCount()) {
             $hookcount = $hook->getBindingCount();
             $bindings = $hook->getBindings();
             foreach ($bindings as $b) {
                 $contents .= sprintf("\nExecuting Binding %s...\n", $b['call']);
                 // Since these systems will just be writing to STDOUT, I'll need to capture that.
                 try {
                     ob_start();
                     $execution = $hook->callBinding($b, array());
                     $executiondata = ob_get_clean();
                 } catch (Exception $e) {
                     $execution = false;
                     $executiondata = 'EXCEPTION: ' . $e->getMessage() . ob_get_clean();
                 }
                 if ($executiondata == '' && $execution) {
                     $contents .= "Cron executed successfully with no output\n";
                     ++$hooksuccesses;
                 } elseif ($execution) {
                     $contents .= $executiondata . "\n";
                     ++$hooksuccesses;
                 } else {
                     $contents .= $executiondata . "\n!!FAILED\n";
                     $overallresult = false;
                 }
             }
         } else {
             $contents = 'No bindings located for requested cron';
             $overallresult = true;
         }
     } else {
         $contents = 'Invalid hook requested: ' . $cron;
         $overallresult = false;
     }
     // Just in case the contents are returning html... (they should be plain text).
     // Replace the most common line endings with things that make sense for plain text.
     // This is to ensure that all the available scenarios are met and saved/displayed without extra whitespace.
     //
     // Since some systems will provide plain text (easy!), windows/os9 line endings,
     // HTML (br and br/), and formatted HTML (br + \n).
     $contents = str_ireplace(["\r\n<br>", "\r\n<br/>", "\r\n<br />", "\n<br>", "\n<br/>", "\n<br />", "<br>", "<br/>", "<br />", "\r\n", "\r"], "\n", $contents);
     // Save the results.
     $log->set('completed', Time::GetCurrentGMT());
     $log->set('duration', microtime(true) * 1000 - $start);
     $log->set('log', $contents);
     $log->set('status', $overallresult ? 'pass' : 'fail');
     $log->save();
     // Make a copy of this in the system log too if applicable.
     // This time is listed in ms
     $time = microtime(true) * 1000 - $start;
     // 0.01 = 10 ns
     // 1    = 1 ms
     // 1000 = 1 second
     if ($time < 1) {
         // TIME is less than 1, which means it executed faster than 1ms, display in nanoseconds.
         $time = round($time, 4) * 1000 . ' ns';
     } elseif ($time < 1000) {
         // TIME is less than 1000, which means it executed faster than 1 second, display in milliseconds.
         $time = round($time, 0) . ' ms';
     } else {
         // TIME is at least 1 second or longer... Display in minutes:seconds, (no need to display 1.453 seconds!)
         // First, convert the milliseconds to seconds; they are more manageable for what I need to do.
         // This will change time from 12345(ms) to 13(seconds)
         $time = ceil($time / 1000);
         $minutes = floor($time / 60);
         $seconds = $time - $minutes * 60;
         if ($minutes > 0) {
             $time = $minutes . 'm ' . str_pad($seconds, 2, '0', STR_PAD_LEFT) . 's';
         } else {
             $time = $seconds . ' seconds';
         }
     }
     if ($hookcount > 0) {
         $msg = 'Cron ' . $cron . ' completed in ' . $time . '.  ' . $hooksuccesses . ' out of ' . $hookcount . ' hooks called successfully.';
         SystemLogModel::LogInfoEvent('/cron/' . $cron, $msg, $contents);
     }
     // Just to notify the calling function.
     return $log;
 }
Beispiel #7
0
<?php
/**
 * Upgrade file for user data from 2.6.1 to 2.6.2.
 *
 * Namely setting the last login for users that have a password set.
 * It's good indication that if they have a password set, that they've logged in already.
 * 
 * @author Charlie Powell <*****@*****.**>
 * @date 20131030.2031
 * @package Core
 */

$timenow = Time::GetCurrentGMT();

// Find and update all user accounts that have a last login of not recorded, but have a password set (legacy data)
$users = UserModel::Find(['password != ', 'last_login = 0']);
foreach($users as $u){
	/** @var $u UserModel */
	$u->set('last_login', $timenow);
	$u->save();
}

// Find and update all user accounts that have a last login of not recorded, but have a password set (legacy data)
$users = UserModel::Find(['password != ', 'last_password = 0']);
foreach($users as $u){
	/** @var $u UserModel */
	$u->set('last_password', $timenow);
	$u->save();
}
Beispiel #8
0
 /**
  * Helper function to save a blog article, both new and existing.
  *
  * @static
  *
  * @param Form $form
  * @return string Redirect URL
  */
 public static function BlogArticleFormHandler(Form $form)
 {
     try {
         /** @var $page PageModel */
         $page = $form->getModel('page');
         /** @var $article BlogArticleModel */
         $article = $form->getModel('model');
         // I need to update some of the article information from the page info.
         $article->set('title', $page->get('title'));
         /** @var $pageauthor PageMetaModel|null */
         $pageauthor = $page->getMeta('author');
         if ($pageauthor && $pageauthor->get('meta_value_title') && $pageauthor->get('meta_value')) {
             // Allow the user to override who is posting this article, if set.
             $article->set('authorid', $pageauthor->get('meta_value'));
         } elseif ($pageauthor && $pageauthor->get('meta_value_title')) {
             // If they never selected a valid user, allow that to go through too.
             // The page will have saved the name that they type in regardless.
             $article->set('authorid', 0);
         } else {
             // Otherwise Set the article author to the current user.
             $article->set('authorid', \Core\user()->get('id'));
             $page->setMeta('author', \Core\user()->getDisplayName());
             $page->setMeta('authorid', \Core\user()->get('id'));
         }
         $isnew = !$article->exists();
         // Blog pages are not selectable.  Otherwise there would just be WAY too many of them!
         // This addresses bug #321
         $page->set('selectable', 0);
         if ($article->get('status') == 'published' && !$article->get('published')) {
             // If it's new and is published... set the published date to right now!
             $article->set('published', Time::GetCurrentGMT());
         }
         $article->save();
         // Set the baseurl and some other data on the page
         $page->set('baseurl', $article->get('baseurl'));
         $page->set('component', 'blog');
         $page->set('editurl', '/blog/article/update/' . $article->get('blogid') . '/' . $article->get('id'));
         $page->save();
         // Clear the page cache
         $page->purgePageCache();
         // if it's new, allow the user to post it to facebook.
         if (isset($_POST['facebook_post']) && $_POST['facebook_post']) {
             // facebook_post
             $token = substr($_POST['facebook_post'], strpos($_POST['facebook_post'], ':') + 1);
             $fbid = substr($_POST['facebook_post'], 0, strpos($_POST['facebook_post'], ':'));
             $from = \Core\user()->get('facebook_id');
             // yay....
             $args = array('access_token' => $token, 'from' => $from, 'link' => \Core\resolve_link($article->get('rewriteurl')), 'name' => $article->get('title'), 'caption' => '', 'description' => $article->getTeaser(), 'message' => '');
             // Some optional arguments
             if ($article->getImage()) {
                 $args['picture'] = $article->getImage()->getPreviewURL('300x300');
             }
             $args['ref'] = 'coreplus';
             $facebook = new Facebook(array('appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET));
             $publish_result = $facebook->api('/' . $fbid . '/feed', 'POST', $args);
             $article->set('fb_account_id', $fbid);
             $article->set('fb_post_id', $publish_result['id']);
             $article->save();
         }
         Core::SetMessage(($isnew ? 'Created' : 'Updated') . ' blog article successfully!', 'success');
         return 'back';
         //return $article->get('baseurl');
     } catch (ModelValidationException $e) {
         Core::SetMessage($e->getMessage(), 'error');
         return false;
     } catch (FacebookApiException $e) {
         // Facebook errors are not critical, as the post is still created.
         Core::SetMessage($e->getMessage(), 'error');
         return $article->get('rewriteurl');
     } catch (Exception $e) {
         \Core\ErrorManagement\exception_handler($e);
         Core::SetMessage($e->getMessage(), 'error');
         return false;
     }
 }