pos/is4c-nf/lib/LocalStorage/CoreLocal.php
<?php
/*******************************************************************************
Copyright 2015 Whole Foods Co-op
This file is part of IT CORE.
IT CORE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
IT CORE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
in the file license.txt along with IT CORE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*********************************************************************************/
use COREPOS\pos\lib\Database;
use COREPOS\pos\lib\JsonLib;
if (!class_exists("COREPOS\\pos\\lib\\LocalStorage\\LocalStorage")) {
include_once(__DIR__ . '/LocalStorage.php');
}
/**
@class CoreLocal
*/
class CoreLocal
{
private static $storageObject = null;
private static $mechanism = 'SessionStorage';
private static $INI_SETTINGS = array(
'laneno',
'store_id',
'localhost',
'DBMS',
'localUser',
'localPass',
'pDatabase',
'tDatabase',
);
/**
Singleton constructor
*/
private static function init()
{
if (class_exists(self::$mechanism)) {
self::$storageObject = new self::$mechanism();
} else {
self::$storageObject = new SessionStorage();
}
}
/**
Get value from session
@param $key [string] variable name
*/
public static function get($key)
{
if (self::$storageObject === null) {
self::init();
}
return self::$storageObject->get($key);
}
/**
Set value in session
@param $key [string] variable name
@param $val [mixed] variable value
@param $immutable [boolean, optional]
@return [mixed] variable value OR empty string if variable
does not exist
*/
public static function set($key, $val, $immutable=false)
{
if (self::$storageObject === null) {
self::init();
}
return self::$storageObject->set($key, $val);
}
/**
Re-read values from config file
*/
public static function refresh()
{
self::init();
self::loadIni();
}
/**
Check whether ini.json has all required settings
If it does not, try to migrate ini.php to ini.json
@return
- true if all settings present or successful migration
- false otherwise
*/
private static function validateJsonIni()
{
$json = dirname(__FILE__) . '/../../ini.json';
$settings = array();
if (!file_exists($json) && !is_writable(dirname(__FILE__) . '/../../')) {
return false;
} elseif (file_exists($json)) {
$settings = self::readIniJson();
$settings = $settings->iteratorKeys();
}
$all = true;
foreach (self::$INI_SETTINGS as $key) {
if (!in_array($key, $settings)) {
$all = false;
break;
}
}
if ($all) {
return true;
}
$jsonStr = self::convertIniPhpToJson();
return file_put_contents($json, $jsonStr) ? true : false;
}
/**
Load values from an ini file.
Will read the first file found from:
1. ini.json
2. ini.php
*/
private static function loadIni()
{
/**
UnitTestStorage is backed by a simple array rather
than $_SESSION. This loads the ini.php settings into
a temporary, *non-global* $CORE_LOCAL and then loops
through to add them to the actual global session
*/
if (!class_exists('COREPOS\\pos\\lib\\LocalStorage\\UnitTestStorage')) {
include(__DIR__ . '/UnitTestStorage.php');
}
$settings = array();
if (!self::get('ValidJson') && self::validateJsonIni()) {
$settings = self::readIniJson();
self::set('ValidJson', true);
} elseif (!self::get('ValidJson') && file_exists(dirname(__FILE__) . '/../../ini.php')) {
$settings = self::readIniPhp();
} elseif (!self::get('ValidJson')) {
self::loadEnv();
}
foreach ($settings as $key => $value) {
if (!in_array($key, self::$INI_SETTINGS)) {
// setting does not belong in ini.php
// eventually these settings should be
// ignored
}
self::set($key, $value, true);
}
}
private static function loadEnv()
{
self::set('laneno', self::getEnvOrDefault('LANENO', 99), true);
self::set('store_id', self::getEnvOrDefault('STOREID', 1), true);
self::set('localhost', self::getEnvOrDefault('LOCALHOST', '127.0.0.1'), true);
self::set('DBMS', self::getEnvOrDefault('DBMS', 'MYSQLI'), true);
self::set('localUser', self::getEnvOrDefault('LOCALUSER', 'root'), true);
self::set('localPass', self::getEnvOrDefault('LOCALPASS', ''));
self::set('pDatabase', self::getEnvOrDefault('PDATABASE', 'opdata'), true);
self::set('tDatabase', self::getEnvOrDefault('TDATABASE', 'translog'), true);
}
private static function getEnvOrDefault($name, $default)
{
$val = getenv($name);
return $val === false ? $default : $val;
}
/**
Examine configuration file. Extract settings
that do not belong in the configuration file,
write them to opdata.parameters, then remove
them from the configuration file
*/
public static function migrateSettings()
{
if (file_exists(dirname(__FILE__).'/../../ini.php')) {
$file = dirname(__FILE__).'/../../ini.php';
$settings = self::readIniPhp();
$dbc = Database::pDataConnect();
foreach ($settings as $key => $value) {
if (!in_array($key, self::$INI_SETTINGS)) {
if ($key == 'NewMagellanPorts' || $key == 'LaneMap') {
continue;
} elseif ($key == 'SpecialDeptMap') {
// SpecialDeptMap has a weird array structure
// and gets moved to a dedicated table
if (CoreLocal::get('NoCompat') == 1 || $dbc->tableExists('SpecialDeptMap')) {
$mapModel = new \COREPOS\pos\lib\models\op\SpecialDeptMapModel($dbc);
$mapModel->initTable($value);
\COREPOS\pos\install\conf\Conf::remove($key);
}
} else {
// other settings go into opdata.parameters
$saved = \COREPOS\pos\install\conf\ParamConf::save($dbc, $key, $value);
if ($saved && is_writable($file)) {
\COREPOS\pos\install\conf\Conf::remove($key);
}
}
}
}
}
}
/**
Read the settings from ini.php and return
an equivalent JSON string
*/
public static function convertIniPhpToJson()
{
$php = dirname(__FILE__) . '/../../ini.php';
$php = self::readIniPhp();
$json = array();
foreach ($php as $key => $val) {
$json[$key] = $val;
}
// this may occur before autoloading has kicked in
if (!class_exists('COREPOS\\pos\\lib\\JsonLib')) {
include(__DIR__ . '/../JsonLib.php');
}
return JsonLib::prettyJSON(json_encode($json));
}
/**
Read settings from ini.php
@return [LocalStorage object] containing the settings
*/
public static function readIniPhp()
{
$php = dirname(__FILE__) . '/../../ini.php';
$CORE_LOCAL = new \COREPOS\pos\lib\LocalStorage\UnitTestStorage();
if (file_exists($php)) {
include($php);
}
return $CORE_LOCAL;
}
/**
Read settings from ini.json
@return [LocalStorage object] containing the settings
*/
public static function readIniJson()
{
$json = dirname(__FILE__) . '/../../ini.json';
$ret = new \COREPOS\pos\lib\LocalStorage\UnitTestStorage();
if (file_exists($json)) {
$encoded = file_get_contents($json);
$decoded = json_decode($encoded, true);
if (is_array($decoded)) {
foreach ($decoded as $key => $val) {
$ret->set($key, $val);
}
}
}
return $ret;
}
/**
Set the LocalStorage class used for storing
session values
@param $m [string] class name
*/
public static function setHandler($mec)
{
self::$mechanism = $mec;
}
/**
Check whether the given variable is immutable
@param $key [string] variable name
@return [boolean]
Only here for unit test compatibility
*/
public static function isImmutable($key)
{
return false;
}
/**
Get list of stored variable names
@return [array] of variable names
LocalStorage objects implement the Iterator
interface. This method helps the WrappedStorage
class that provides backward compatibillity
between $CORE_LOCAL and CoreLocal meet
the interface requirements.
*/
public static function iteratorKeys()
{
if (self::$storageObject === null) {
self::init();
}
return self::$storageObject->iteratorKeys();
}
}