/home
/deploy
/EHungry-6-boyan
/Web
/classes
/Cache.class.php
}
public static function SetObject($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetArray($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetBoolean($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function Set($key, $var, $expire = 86400) {
App::debugbarLog('debug', "Cache set: $key");
if ($i = static::getInstance()) {
$var = static::beforeSet($var);
return $expire > 0?
$i->setEx($key, $expire, $var) :
$i->set($key, $var);
}
return null;
}
public static function Exists(...$key):?bool {
if ($i = static::getInstance()) {
return $i->exists($key);
}
return null;
}
public static function Expire($key, $ttl) {
if ($i = static::getInstance()) {
return $i->expire($key, $ttl);
}
return false;
}
/**
Arguments
"MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error."
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/Cache.class.php
}
public static function SetObject($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetArray($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetBoolean($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function Set($key, $var, $expire = 86400) {
App::debugbarLog('debug', "Cache set: $key");
if ($i = static::getInstance()) {
$var = static::beforeSet($var);
return $expire > 0?
$i->setEx($key, $expire, $var) :
$i->set($key, $var);
}
return null;
}
public static function Exists(...$key):?bool {
if ($i = static::getInstance()) {
return $i->exists($key);
}
return null;
}
public static function Expire($key, $ttl) {
if ($i = static::getInstance()) {
return $i->expire($key, $ttl);
}
return false;
}
/**
Arguments
"bc_configuration_1"
86400
"""
O:13:"Configuration":27:{s:10:"timestamps";b:1;s:11:"\x00*\x00fillable";a:1:{i:0;s:14:"sentry_enabled";}s:8:"\x00*\x00casts";a:3:{s:14:"sentry_enabled";s:7:"boolean";s:15:"sentry_projects";s:4:"json";s:15:"taxcloud_states";s:4:"json";}s:12:"pdfPageCount";i:0;s:9:"\x00*\x00hidden";a:1:{i:0;s:8:"password";}s:12:"\x00*\x00nullables";a:0:{}s:13:"\x00*\x00connection";s:7:"default";s:8:"\x00*\x00table";N;s:13:"\x00*\x00primaryKey";s:2:"id";s:10:"\x00*\x00keyType";s:3:"int";s:12:"incrementing";b:1;s:7:"\x00*\x00with";a:0:{}s:12:"\x00*\x00withCount";a:0:{}s:10:"\x00*\x00perPage";i:15;s:6:"exists";b:1;s:18:"wasRecentlyCreated";b:0;s:13:"\x00*\x00attributes";a:19:{s:2:"id";i:1;s:11:"modified_at";s:19:"2025-10-06 05:49:39";s:11:"force_email";s:3:"SES";s:22:"enabled_phone_services";s:28:"["TWILIO","TELNYX","VONAGE"]";s:26:"enabled_order_sms_services";s:27:"["TWILIO","NEXMO","TELNYX"]";s:19:"order_sms_hide_link";i:0;s:22:"enabled_url_shorteners";s:138:"{"TWILIO":["Random Short Host"],"PLIVO":[],"NEXMO":["Random Short Host"],"BANDWIDTH":["Random Short Host"],"TELNYX":["Random Short Host"]}";s:20:"enabled_fax_services";s:19:"["TWILIO","PHAXIO"]";s:20:"enabled_sms_services";s:35:"["TWILIO","PLIVO","NEXMO","TELNYX"]";s:16:"reseller_user_id";i:0;s:16:"use_advanced_tts";i:0;s:14:"sentry_enabled";i:1;s:15:"sentry_projects";s:146:"[{"name":"manager","dsn":"https://4f3bae433a8449d8b3752a0d7eedebce@o4504561268424704.ingest.sentry.io/4504630628777984","rate":20,"enabled":true}]";s:35:"payment_aggregator_checkout_message";s:123:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:39:"payment_aggregator_confirmation_message";s:112:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>";s:32:"payment_aggregator_email_message";s:117:"<p>The charge will show up as "<strong>{PAYMENT_LINK}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:38:"payment_aggregator_order_sheet_message";s:104:"<p>The charge will show up as "{PAYMENT_AGGREGATOR}" on the customer's credit card / bank statement.</p>";s:28:"third_party_delivery_enabled";i:1;s:15:"taxcloud_states";s:31:"["DC","AK","ID","ME","NM","TX"]";}s:11:"\x00*\x00original";a:19:{s:2:"id";i:1;s:11:"modified_at";s:19:"2025-10-06 05:49:39";s:11:"force_email";s:3:"SES";s:22:"enabled_phone_services";s:28:"["TWILIO","TELNYX","VONAGE"]";s:26:"enabled_order_sms_services";s:27:"["TWILIO","NEXMO","TELNYX"]";s:19:"order_sms_hide_link";i:0;s:22:"enabled_url_shorteners";s:138:"{"TWILIO":["Random Short Host"],"PLIVO":[],"NEXMO":["Random Short Host"],"BANDWIDTH":["Random Short Host"],"TELNYX":["Random Short Host"]}";s:20:"enabled_fax_services";s:19:"["TWILIO","PHAXIO"]";s:20:"enabled_sms_services";s:35:"["TWILIO","PLIVO","NEXMO","TELNYX"]";s:16:"reseller_user_id";i:0;s:16:"use_advanced_tts";i:0;s:14:"sentry_enabled";i:1;s:15:"sentry_projects";s:146:"[{"name":"manager","dsn":"https://4f3bae433a8449d8b3752a0d7eedebce@o4504561268424704.ingest.sentry.io/4504630628777984","rate":20,"enabled":true}]";s:35:"payment_aggregator_checkout_message";s:123:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:39:"payment_aggregator_confirmation_message";s:112:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>";s:32:"payment_aggregator_email_message";s:117:"<p>The charge will show up as "<strong>{PAYMENT_LINK}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:38:"payment_aggregator_order_sheet_message";s:104:"<p>The charge will show up as "{PAYMENT_AGGREGATOR}" on the customer's credit card / bank statement.</p>";s:28:"third_party_delivery_enabled";i:1;s:15:"taxcloud_states";s:31:"["DC","AK","ID","ME","NM","TX"]";}s:8:"\x00*\x00dates";a:0:{}s:13:"\x00*\x00dateFormat";N;s:10:"\x00*\x00appends";a:0:{}s:9:"\x00*\x00events";a:0:{}s:14:"\x00*\x00observables";a:0:{}s:12:"\x00*\x00relations";a:0:{}s:10:"\x00*\x00touches";a:0:{}s:10:"\x00*\x00visible";a:0:{}s:10:"\x00*\x00guarded";a:1:{i:0;s:1:"*";}}
"""
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/Cache.class.php
public static function getInstance() {
if (static::$redisObj === null) {
static::$redisObj = new Redis();
try {
if (!@static::$redisObj->connect(static::$host, (int)static::$port)) {
static::$redisObj = false;
Splunk::log(Splunk::LOG_REDIS_CONN, ['error' => 'Error connecting']);
} else {
static::$redisObj->select(static::$db);
}
} catch (RedisException $e) {
static::$redisObj = false;
Splunk::log(Splunk::LOG_REDIS_CONN, ['error' => 'Error connecting: '.$e->getMessage()]);
}
}
return static::$redisObj;
}
public static function SetObject($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetArray($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function SetBoolean($key, $var, $expire = 86400) {
return static::Set($key, serialize($var), $expire);
}
public static function Set($key, $var, $expire = 86400) {
App::debugbarLog('debug', "Cache set: $key");
if ($i = static::getInstance()) {
$var = static::beforeSet($var);
return $expire > 0?
$i->setEx($key, $expire, $var) :
$i->set($key, $var);
}
return null;
}
Arguments
"bc_configuration_1"
"""
O:13:"Configuration":27:{s:10:"timestamps";b:1;s:11:"\x00*\x00fillable";a:1:{i:0;s:14:"sentry_enabled";}s:8:"\x00*\x00casts";a:3:{s:14:"sentry_enabled";s:7:"boolean";s:15:"sentry_projects";s:4:"json";s:15:"taxcloud_states";s:4:"json";}s:12:"pdfPageCount";i:0;s:9:"\x00*\x00hidden";a:1:{i:0;s:8:"password";}s:12:"\x00*\x00nullables";a:0:{}s:13:"\x00*\x00connection";s:7:"default";s:8:"\x00*\x00table";N;s:13:"\x00*\x00primaryKey";s:2:"id";s:10:"\x00*\x00keyType";s:3:"int";s:12:"incrementing";b:1;s:7:"\x00*\x00with";a:0:{}s:12:"\x00*\x00withCount";a:0:{}s:10:"\x00*\x00perPage";i:15;s:6:"exists";b:1;s:18:"wasRecentlyCreated";b:0;s:13:"\x00*\x00attributes";a:19:{s:2:"id";i:1;s:11:"modified_at";s:19:"2025-10-06 05:49:39";s:11:"force_email";s:3:"SES";s:22:"enabled_phone_services";s:28:"["TWILIO","TELNYX","VONAGE"]";s:26:"enabled_order_sms_services";s:27:"["TWILIO","NEXMO","TELNYX"]";s:19:"order_sms_hide_link";i:0;s:22:"enabled_url_shorteners";s:138:"{"TWILIO":["Random Short Host"],"PLIVO":[],"NEXMO":["Random Short Host"],"BANDWIDTH":["Random Short Host"],"TELNYX":["Random Short Host"]}";s:20:"enabled_fax_services";s:19:"["TWILIO","PHAXIO"]";s:20:"enabled_sms_services";s:35:"["TWILIO","PLIVO","NEXMO","TELNYX"]";s:16:"reseller_user_id";i:0;s:16:"use_advanced_tts";i:0;s:14:"sentry_enabled";i:1;s:15:"sentry_projects";s:146:"[{"name":"manager","dsn":"https://4f3bae433a8449d8b3752a0d7eedebce@o4504561268424704.ingest.sentry.io/4504630628777984","rate":20,"enabled":true}]";s:35:"payment_aggregator_checkout_message";s:123:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:39:"payment_aggregator_confirmation_message";s:112:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>";s:32:"payment_aggregator_email_message";s:117:"<p>The charge will show up as "<strong>{PAYMENT_LINK}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:38:"payment_aggregator_order_sheet_message";s:104:"<p>The charge will show up as "{PAYMENT_AGGREGATOR}" on the customer's credit card / bank statement.</p>";s:28:"third_party_delivery_enabled";i:1;s:15:"taxcloud_states";s:31:"["DC","AK","ID","ME","NM","TX"]";}s:11:"\x00*\x00original";a:19:{s:2:"id";i:1;s:11:"modified_at";s:19:"2025-10-06 05:49:39";s:11:"force_email";s:3:"SES";s:22:"enabled_phone_services";s:28:"["TWILIO","TELNYX","VONAGE"]";s:26:"enabled_order_sms_services";s:27:"["TWILIO","NEXMO","TELNYX"]";s:19:"order_sms_hide_link";i:0;s:22:"enabled_url_shorteners";s:138:"{"TWILIO":["Random Short Host"],"PLIVO":[],"NEXMO":["Random Short Host"],"BANDWIDTH":["Random Short Host"],"TELNYX":["Random Short Host"]}";s:20:"enabled_fax_services";s:19:"["TWILIO","PHAXIO"]";s:20:"enabled_sms_services";s:35:"["TWILIO","PLIVO","NEXMO","TELNYX"]";s:16:"reseller_user_id";i:0;s:16:"use_advanced_tts";i:0;s:14:"sentry_enabled";i:1;s:15:"sentry_projects";s:146:"[{"name":"manager","dsn":"https://4f3bae433a8449d8b3752a0d7eedebce@o4504561268424704.ingest.sentry.io/4504630628777984","rate":20,"enabled":true}]";s:35:"payment_aggregator_checkout_message";s:123:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:39:"payment_aggregator_confirmation_message";s:112:"<p>The charge will show up as "<strong>{PAYMENT_AGGREGATOR}" </strong>on your credit card / bank statement.</p>";s:32:"payment_aggregator_email_message";s:117:"<p>The charge will show up as "<strong>{PAYMENT_LINK}" </strong>on your credit card / bank statement.</p>\n
\n
<p> </p>";s:38:"payment_aggregator_order_sheet_message";s:104:"<p>The charge will show up as "{PAYMENT_AGGREGATOR}" on the customer's credit card / bank statement.</p>";s:28:"third_party_delivery_enabled";i:1;s:15:"taxcloud_states";s:31:"["DC","AK","ID","ME","NM","TX"]";}s:8:"\x00*\x00dates";a:0:{}s:13:"\x00*\x00dateFormat";N;s:10:"\x00*\x00appends";a:0:{}s:9:"\x00*\x00events";a:0:{}s:14:"\x00*\x00observables";a:0:{}s:12:"\x00*\x00relations";a:0:{}s:10:"\x00*\x00touches";a:0:{}s:10:"\x00*\x00visible";a:0:{}s:10:"\x00*\x00guarded";a:1:{i:0;s:1:"*";}}
"""
86400
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/BaseClass.class.php
}
/**
* Returns the cached object, if it {@link BaseClass::SHOULD_BE_CACHED} and valid, given the $id.
* @param $id
* @return false|static
*/
protected function cacheGet($id) {
if (static::SHOULD_BE_CACHED && $id > 0 && $cache = Cache::GetObject($this->getCacheKey($id))) {
return $cache;
}
return false;
}
/**
* Caches the current object, if {@link BaseClass::SHOULD_BE_CACHED}.
*/
protected function cacheSet() {
if (static::SHOULD_BE_CACHED && $this->id > 0) {
Cache::SetObject($this->getCacheKey(), $this, static::CACHE_EXPIRATION);
}
}
/**
* Removes the current object from cache, if {@link BaseClass::SHOULD_BE_CACHED}.
*/
public function cacheDelete() {
if (static::SHOULD_BE_CACHED && $this->id > 0) {
Cache::Delete($this->getCacheKey());
}
}
/**
* Removes all objects from cache, if {@link BaseClass::SHOULD_BE_CACHED}.
*/
public static function cacheDeleteAll($chunkSize = self::CACHE_DELETE_CHUNK_SIZE) {
if (static::SHOULD_BE_CACHED) {
static::chunk($chunkSize, function ($chunk) {
foreach ($chunk as $row) {
$row->cacheDelete();
Arguments
"bc_configuration_1"
Configuration {}
86400
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/BaseClass.class.php
* @param int|int[] $id
* @param array $columns
* @return static|Collection|static[]|null
* @todo why isn't this protected?
* @fixme side-effect of this workaround: the cache is silently skipped when running query-modifiers like ResellerUser::withoutGlobalScope('main_resellers')->find(123)
*/
public function findNew($id, $columns = ['*']) {
if (is_array($id)) {
return $this->directFind($id, $columns);
}
if ($cached = $this->cacheGet($id)) {
return $cached;
}
/** @var static $result */
$result = $this->directFind($id, $columns);
if ($result && $columns == ['*']) {
$result->cacheSet();
}
return $result;
}
/**
* Finds one or more entries in the database. In case of single-finds, checks the cache layer first.
* @see BaseClass::SHOULD_BE_CACHED
* @see Cache
* @param int|int[] $id
* @param array $columns
* @return Collection|static|static[]|null
*/
public static function find($id, $columns = ['*']) {
return (new static)->findNew($id, $columns);
}
//FIXME: we're missing cached versions for findOrFail and findOrNew, at the very least
/** @deprecated use {@link save()} instead */
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/BaseClass.class.php
/** @var static $result */
$result = $this->directFind($id, $columns);
if ($result && $columns == ['*']) {
$result->cacheSet();
}
return $result;
}
/**
* Finds one or more entries in the database. In case of single-finds, checks the cache layer first.
* @see BaseClass::SHOULD_BE_CACHED
* @see Cache
* @param int|int[] $id
* @param array $columns
* @return Collection|static|static[]|null
*/
public static function find($id, $columns = ['*']) {
return (new static)->findNew($id, $columns);
}
//FIXME: we're missing cached versions for findOrFail and findOrNew, at the very least
/** @deprecated use {@link save()} instead */
public function store() {
return $this->save();
}
/**
* Overrides the original save to return the generated ID.
* After saving, caching ({@link SHOULD_BE_CACHED}) and logging ({@link willLogChanges()}/{@link loggingChanges()})
* are done, if enabled.
* @param array $options The only option available is "touch" (which is true by default); setting it to false will
* disable "touching" parent relationships (aka belongsTo/belongsToMany) listed in
* {@link $touches}, which updates their timestamps upon a successful save.
* See https://laravel.com/docs/5.4/eloquent-relationships#touching-parent-timestamps
* @return bool|int Returns the ID in case of a successful operation, or false instead.
*/
public function save(array $options = []) {
Arguments
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/BaseClass.class.php
* Stores which classes had their logging behavior overwritten during runtime.
* @var array
* @see willLogChanges()
*/
private static $overwrittenLogChanges = [];
/**
* @var array Indicates the fields which should be placed in the restaurant's timezone when casting to JSON
* @see addDateAttributesToArray()
* @see https://github.com/ehungry/EHungry/wiki/Data-standards#timezone-less-restaurant-times
*/
protected static $restaurantDates = [];
/**
* @param int|array|ParameterHandler $idOrAttr An ID, so the entry is loaded from the database, or a list of attributes to be pre-filled into a new entry.
*/
public function __construct($idOrAttr = null) {
if (is_numeric($idOrAttr)) {
//legacy behavior
if ($entry = static::find($idOrAttr)) {
//TODO: find a way to have default attributes respected in the same way Eloquent does - probably a mix of array_merge() and array_filter() (so we clear empty values from the found entry), or maybe we'll need a custom merger so the final attribute array doesn't miss any field
$this->setRawAttributes($entry->attributes, true);
$this->exists = true;
}
$this->setAttribute('id', $idOrAttr);
parent::__construct();
} elseif (is_array($idOrAttr) || $idOrAttr instanceof ParameterHandler) {
parent::__construct($idOrAttr); //default Eloquent behavior + our custom fill()
} else {
$this->setAttribute('id', -1); //FIXME: legacy behavior as well... can we ditch this someday please????
parent::__construct();
}
}
/**
* We've overwritten the original query builder to include extra methods :)
* @param \Illuminate\Database\Query\Builder $query
* @return Builder|EloquentModel|eHungry\Illuminate\Database\Eloquent\Builder
*/
public function newEloquentBuilder($query) {
Arguments
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/Configuration.class.php
];
public const SERVICES_PHONE = [
'TWILIO',
'TELNYX',
'VONAGE'
];
public const SERVICES_FAX = [
'PHAXIO',
'TELNYX',
'CONCORD'
];
public const SERVICES_URL_SHORTENERS = [
'Random Short Host'
];
public static function getDefault() {
return new self(1);
}
public static function getEmail($account) {
$reseller_user_id = is_object($account) ? $account->getResellerUserId() : null;
$config = self::getDefault();
if ($config->force_email == 'DEFAULT' && $reseller_user_id) {
$config = self::getByResellerUserId($reseller_user_id);
}
return $config->force_email;
}
/**
* @param string $serviceType
* @param Account|null $account
* @param string[] $exclude Services already tried
* @param string $default
* @param string $useServiceIfEnabled Prefer this service if it's enabled and not excluded
* @return bool|string First eligible service or false if none
*/
private static function getService($serviceType, $account, $exclude, $default, $useServiceIfEnabled = '') {
Arguments
/home
/deploy
/EHungry-6-boyan
/Web
/classes
/ErrorHandlers.class.php
}
/**
* Starts up Sentry reporting with common options for all subsystems.
*
* Implementation note: Since this might end up running twice (first for the general "backend" reporter, which will capture early-setup errors and errors from smaller sub-projects, and the second run for capturing anything related to a relevant controller), static vars are used in some spots.
*
* NOTE: Originally, this method was to be called very early in the runtime (right after importing the autoloaders), but it was decided it wouldn't be that useful (given we already have our own Alerts and all), so it got moved down in the runtime to capture errors only from backend-enabled sub-projects.
*
* @param string $controller The selected subsystem controller, once we arrive there. If there's no specific project in Sentry for this controller, reports will fall under the general "Backend" project.
* @return void
*/
public static function sentryInit($controller = null) {
$timing = microtime(true);
//load config details from the database
static $projects = null;
static $disabled = false;
if (is_null($projects)) {
$eHungryConfig = Configuration::getDefault();
$disabled = !$eHungryConfig->sentry_enabled;
$projects = collect($eHungryConfig->sentry_projects)
->keyBy('name')
->toArray();
}
//check for Sentry as a whole being disabled
if ($disabled) {
trigger_error("Sentry is disabled by the backend (/rcs?form=sentry) (called for '$controller')", E_USER_WARNING);
return;
}
//check if the given project is disabled - if it's not found, it gets reported under the generic "backend" project with a tag, so we should allow for that too
$nonProjectController = false;
if ($controller) {
$mainController = substr($controller, 0, strpos($controller, '_ajax'))?: $controller;
if (isset($projects[$mainController])) {
if (!$projects[$mainController]['enabled']) {
trigger_error("Sentry seems to be disabled for this controller ($controller). Check at /rcs?form=sentry", E_USER_WARNING);
return;
/home
/deploy
/EHungry-6-boyan
/Web
/index.php
//TODO create a «root»/_bootstrap.php which can be used by .psysh.php, tests/bootstrap.php and Web/index.php
require(dirname(__DIR__).'/PHP/base_consts.php');
require(dirname(__DIR__).'/PHP/autoloader.php');
initializeAutoLoader();
//disabled for now since we already have our own Alerts infrastructure, and it's not worth it to append another cloud provider to the startup of every freaking request; it's also not possible to catch errors this early if we depend on database checks, but we'll leave it here in case we change our mind?
//ErrorHandlers::sentryInit(); //early catch of errors and failsafe for smaller controllers, not in Sentry
App::startTime();
ErrorHandlers::register();
// Global.php is the core setup file for the application
App::debugbarTime('Global.php');
require(dirname(__DIR__) . '/PHP/Global.php');
App::debugbarTime('Global.php');
/** @var string $controller The main controller - defined at /PHP/Global.php */
App::debugbarTime('Sentry - controller');
ErrorHandlers::sentryInit($controller); //doesn't always do much - not every controller has a Sentry project
App::debugbarTime('Sentry - controller');
App::debugbarTime("controller: $controller");
apache_note('AppController', $controller);
if (file_exists(CORE_PATH."lib/helpers/$controller.php")) {
require CORE_PATH."lib/helpers/$controller.php";
}
require CORE_PATH."controllers/$controller.php";
App::debugbarTime("controller: $controller");
Arguments