From abff6d2655370a9138b11ef997c6ce8b648f8f7c Mon Sep 17 00:00:00 2001 From: RezaMohammadi99 Date: Tue, 7 May 2019 15:51:14 +0000 Subject: [PATCH 01/13] Fixed Parameter search rounding error. This commit sets the default precision of part parameter searching to femto to maintain fractional values. --- app/SymfonyRequirements.php | 806 ++++++++++++++++++ app/check.php | 141 +++ app/config/config_framework.yml | 7 + app/config/paramters.php | 272 ++++++ app/logs/.htaccess | 2 - app/logs/ignore.json | 3 - composer.json | 4 +- .../Resources/public/css/PartKeepr.css | 2 +- .../public/images/become_a_patron_button.xcf | Bin 0 -> 8721 bytes .../public/js/Components/Part/PartsGrid.js | 5 +- .../Components/Project/ProjectReportGrid.js | 2 +- src/PartKeepr/PartBundle/Entity/Part.php | 9 +- .../StockBundle/Entity/StockEntry.php | 2 +- web/phpinfo.php | 6 + 14 files changed, 1247 insertions(+), 14 deletions(-) create mode 100644 app/SymfonyRequirements.php create mode 100644 app/check.php create mode 100644 app/config/paramters.php delete mode 100644 app/logs/.htaccess delete mode 100644 app/logs/ignore.json create mode 100644 src/PartKeepr/FrontendBundle/Resources/public/images/become_a_patron_button.xcf create mode 100644 web/phpinfo.php diff --git a/app/SymfonyRequirements.php b/app/SymfonyRequirements.php new file mode 100644 index 000000000..b21edde67 --- /dev/null +++ b/app/SymfonyRequirements.php @@ -0,0 +1,806 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* + * Users of PHP 5.2 should be able to run the requirements checks. + * This is why the file and all classes must be compatible with PHP 5.2+ + * (e.g. not using namespaces and closures). + * + * ************** CAUTION ************** + * + * DO NOT EDIT THIS FILE as it will be overridden by Composer as part of + * the installation/update process. The original file resides in the + * SensioDistributionBundle. + * + * ************** CAUTION ************** + */ + +/** + * Represents a single PHP requirement, e.g. an installed extension. + * It can be a mandatory requirement or an optional recommendation. + * There is a special subclass, named PhpIniRequirement, to check a php.ini configuration. + * + * @author Tobias Schultze + */ +class Requirement +{ + private $fulfilled; + private $testMessage; + private $helpText; + private $helpHtml; + private $optional; + + /** + * Constructor that initializes the requirement. + * + * @param bool $fulfilled Whether the requirement is fulfilled + * @param string $testMessage The message for testing the requirement + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement + */ + public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false) + { + $this->fulfilled = (bool) $fulfilled; + $this->testMessage = (string) $testMessage; + $this->helpHtml = (string) $helpHtml; + $this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText; + $this->optional = (bool) $optional; + } + + /** + * Returns whether the requirement is fulfilled. + * + * @return bool true if fulfilled, otherwise false + */ + public function isFulfilled() + { + return $this->fulfilled; + } + + /** + * Returns the message for testing the requirement. + * + * @return string The test message + */ + public function getTestMessage() + { + return $this->testMessage; + } + + /** + * Returns the help text for resolving the problem. + * + * @return string The help text + */ + public function getHelpText() + { + return $this->helpText; + } + + /** + * Returns the help text formatted in HTML. + * + * @return string The HTML help + */ + public function getHelpHtml() + { + return $this->helpHtml; + } + + /** + * Returns whether this is only an optional recommendation and not a mandatory requirement. + * + * @return bool true if optional, false if mandatory + */ + public function isOptional() + { + return $this->optional; + } +} + +/** + * Represents a PHP requirement in form of a php.ini configuration. + * + * @author Tobias Schultze + */ +class PhpIniRequirement extends Requirement +{ + /** + * Constructor that initializes the requirement. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement + */ + public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false) + { + $cfgValue = ini_get($cfgName); + + if (is_callable($evaluation)) { + if (null === $testMessage || null === $helpHtml) { + throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.'); + } + + $fulfilled = call_user_func($evaluation, $cfgValue); + } else { + if (null === $testMessage) { + $testMessage = sprintf('%s %s be %s in php.ini', + $cfgName, + $optional ? 'should' : 'must', + $evaluation ? 'enabled' : 'disabled' + ); + } + + if (null === $helpHtml) { + $helpHtml = sprintf('Set %s to %s in php.ini*.', + $cfgName, + $evaluation ? 'on' : 'off' + ); + } + + $fulfilled = $evaluation == $cfgValue; + } + + parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional); + } +} + +/** + * A RequirementCollection represents a set of Requirement instances. + * + * @author Tobias Schultze + */ +class RequirementCollection implements IteratorAggregate +{ + /** + * @var Requirement[] + */ + private $requirements = array(); + + /** + * Gets the current RequirementCollection as an Iterator. + * + * @return Traversable A Traversable interface + */ + public function getIterator() + { + return new ArrayIterator($this->requirements); + } + + /** + * Adds a Requirement. + * + * @param Requirement $requirement A Requirement instance + */ + public function add(Requirement $requirement) + { + $this->requirements[] = $requirement; + } + + /** + * Adds a mandatory requirement. + * + * @param bool $fulfilled Whether the requirement is fulfilled + * @param string $testMessage The message for testing the requirement + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null) + { + $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false)); + } + + /** + * Adds an optional recommendation. + * + * @param bool $fulfilled Whether the recommendation is fulfilled + * @param string $testMessage The message for testing the recommendation + * @param string $helpHtml The help text formatted in HTML for resolving the problem + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null) + { + $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true)); + } + + /** + * Adds a mandatory requirement in form of a php.ini configuration. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) + { + $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false)); + } + + /** + * Adds an optional recommendation in form of a php.ini configuration. + * + * @param string $cfgName The configuration name used for ini_get() + * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, + * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement + * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. + * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. + * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. + * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) + * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) + * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) + */ + public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) + { + $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true)); + } + + /** + * Adds a requirement collection to the current set of requirements. + * + * @param RequirementCollection $collection A RequirementCollection instance + */ + public function addCollection(RequirementCollection $collection) + { + $this->requirements = array_merge($this->requirements, $collection->all()); + } + + /** + * Returns both requirements and recommendations. + * + * @return Requirement[] + */ + public function all() + { + return $this->requirements; + } + + /** + * Returns all mandatory requirements. + * + * @return Requirement[] + */ + public function getRequirements() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns the mandatory requirements that were not met. + * + * @return Requirement[] + */ + public function getFailedRequirements() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && !$req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns all optional recommendations. + * + * @return Requirement[] + */ + public function getRecommendations() + { + $array = array(); + foreach ($this->requirements as $req) { + if ($req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns the recommendations that were not met. + * + * @return Requirement[] + */ + public function getFailedRecommendations() + { + $array = array(); + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && $req->isOptional()) { + $array[] = $req; + } + } + + return $array; + } + + /** + * Returns whether a php.ini configuration is not correct. + * + * @return bool php.ini configuration problem? + */ + public function hasPhpIniConfigIssue() + { + foreach ($this->requirements as $req) { + if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) { + return true; + } + } + + return false; + } + + /** + * Returns the PHP configuration file (php.ini) path. + * + * @return string|false php.ini file path + */ + public function getPhpIniConfigPath() + { + return get_cfg_var('cfg_file_path'); + } +} + +/** + * This class specifies all requirements and optional recommendations that + * are necessary to run the Symfony Standard Edition. + * + * @author Tobias Schultze + * @author Fabien Potencier + */ +class SymfonyRequirements extends RequirementCollection +{ + const LEGACY_REQUIRED_PHP_VERSION = '5.3.3'; + const REQUIRED_PHP_VERSION = '5.5.9'; + + /** + * Constructor that initializes the requirements. + */ + public function __construct() + { + /* mandatory requirements follow */ + + $installedPhpVersion = phpversion(); + $requiredPhpVersion = $this->getPhpRequiredVersion(); + + $this->addRecommendation( + $requiredPhpVersion, + 'Vendors should be installed in order to check all requirements.', + 'Run the composer install command.', + 'Run the "composer install" command.' + ); + + if (false !== $requiredPhpVersion) { + $this->addRequirement( + version_compare($installedPhpVersion, $requiredPhpVersion, '>='), + sprintf('PHP version must be at least %s (%s installed)', $requiredPhpVersion, $installedPhpVersion), + sprintf('You are running PHP version "%s", but Symfony needs at least PHP "%s" to run. + Before using Symfony, upgrade your PHP installation, preferably to the latest version.', + $installedPhpVersion, $requiredPhpVersion), + sprintf('Install PHP %s or newer (installed version is %s)', $requiredPhpVersion, $installedPhpVersion) + ); + } + + $this->addRequirement( + version_compare($installedPhpVersion, '5.3.16', '!='), + 'PHP version must not be 5.3.16 as Symfony won\'t work properly with it', + 'Install PHP 5.3.17 or newer (or downgrade to an earlier PHP version)' + ); + + $this->addRequirement( + is_dir(__DIR__.'/../vendor/composer'), + 'Vendor libraries must be installed', + 'Vendor libraries are missing. Install composer following instructions from http://getcomposer.org/. '. + 'Then run "php composer.phar install" to install them.' + ); + + $cacheDir = is_dir(__DIR__.'/../var/cache') ? __DIR__.'/../var/cache' : __DIR__.'/cache'; + + $this->addRequirement( + is_writable($cacheDir), + 'app/cache/ or var/cache/ directory must be writable', + 'Change the permissions of either "app/cache/" or "var/cache/" directory so that the web server can write into it.' + ); + + $logsDir = is_dir(__DIR__.'/../var/logs') ? __DIR__.'/../var/logs' : __DIR__.'/logs'; + + $this->addRequirement( + is_writable($logsDir), + 'app/logs/ or var/logs/ directory must be writable', + 'Change the permissions of either "app/logs/" or "var/logs/" directory so that the web server can write into it.' + ); + + $this->addPhpIniRequirement( + 'date.timezone', true, false, + 'date.timezone setting must be set', + 'Set the "date.timezone" setting in php.ini* (like Europe/Paris).' + ); + + if (false !== $requiredPhpVersion && version_compare($installedPhpVersion, $requiredPhpVersion, '>=')) { + $timezones = array(); + foreach (DateTimeZone::listAbbreviations() as $abbreviations) { + foreach ($abbreviations as $abbreviation) { + $timezones[$abbreviation['timezone_id']] = true; + } + } + + $this->addRequirement( + isset($timezones[@date_default_timezone_get()]), + sprintf('Configured default timezone "%s" must be supported by your installation of PHP', @date_default_timezone_get()), + 'Your default timezone is not supported by PHP. Check for typos in your php.ini file and have a look at the list of deprecated timezones at http://php.net/manual/en/timezones.others.php.' + ); + } + + $this->addRequirement( + function_exists('iconv'), + 'iconv() must be available', + 'Install and enable the iconv extension.' + ); + + $this->addRequirement( + function_exists('json_encode'), + 'json_encode() must be available', + 'Install and enable the JSON extension.' + ); + + $this->addRequirement( + function_exists('session_start'), + 'session_start() must be available', + 'Install and enable the session extension.' + ); + + $this->addRequirement( + function_exists('ctype_alpha'), + 'ctype_alpha() must be available', + 'Install and enable the ctype extension.' + ); + + $this->addRequirement( + function_exists('token_get_all'), + 'token_get_all() must be available', + 'Install and enable the Tokenizer extension.' + ); + + $this->addRequirement( + function_exists('simplexml_import_dom'), + 'simplexml_import_dom() must be available', + 'Install and enable the SimpleXML extension.' + ); + + if (function_exists('apc_store') && ini_get('apc.enabled')) { + if (version_compare($installedPhpVersion, '5.4.0', '>=')) { + $this->addRequirement( + version_compare(phpversion('apc'), '3.1.13', '>='), + 'APC version must be at least 3.1.13 when using PHP 5.4', + 'Upgrade your APC extension (3.1.13+).' + ); + } else { + $this->addRequirement( + version_compare(phpversion('apc'), '3.0.17', '>='), + 'APC version must be at least 3.0.17', + 'Upgrade your APC extension (3.0.17+).' + ); + } + } + + $this->addPhpIniRequirement('detect_unicode', false); + + if (extension_loaded('suhosin')) { + $this->addPhpIniRequirement( + 'suhosin.executor.include.whitelist', + create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'), + false, + 'suhosin.executor.include.whitelist must be configured correctly in php.ini', + 'Add "phar" to suhosin.executor.include.whitelist in php.ini*.' + ); + } + + if (extension_loaded('xdebug')) { + $this->addPhpIniRequirement( + 'xdebug.show_exception_trace', false, true + ); + + $this->addPhpIniRequirement( + 'xdebug.scream', false, true + ); + + $this->addPhpIniRecommendation( + 'xdebug.max_nesting_level', + create_function('$cfgValue', 'return $cfgValue > 100;'), + true, + 'xdebug.max_nesting_level should be above 100 in php.ini', + 'Set "xdebug.max_nesting_level" to e.g. "250" in php.ini* to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.' + ); + } + + $pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null; + + $this->addRequirement( + null !== $pcreVersion, + 'PCRE extension must be available', + 'Install the PCRE extension (version 8.0+).' + ); + + if (extension_loaded('mbstring')) { + $this->addPhpIniRequirement( + 'mbstring.func_overload', + create_function('$cfgValue', 'return (int) $cfgValue === 0;'), + true, + 'string functions should not be overloaded', + 'Set "mbstring.func_overload" to 0 in php.ini* to disable function overloading by the mbstring extension.' + ); + } + + /* optional recommendations follow */ + + if (file_exists(__DIR__.'/../vendor/composer')) { + require_once __DIR__.'/../vendor/autoload.php'; + + try { + $r = new ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle'); + + $contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php'); + } catch (ReflectionException $e) { + $contents = ''; + } + $this->addRecommendation( + file_get_contents(__FILE__) === $contents, + 'Requirements file should be up-to-date', + 'Your requirements file is outdated. Run composer install and re-check your configuration.' + ); + } + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.3.4', '>='), + 'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions', + 'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.3.8', '>='), + 'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156', + 'Install PHP 5.3.8 or newer if your project uses annotations.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.4.0', '!='), + 'You should not use PHP 5.4.0 due to the PHP bug #61453', + 'Your project might not work properly due to the PHP bug #61453 ("Cannot dump definitions which have method calls"). Install PHP 5.4.1 or newer.' + ); + + $this->addRecommendation( + version_compare($installedPhpVersion, '5.4.11', '>='), + 'When using the logout handler from the Symfony Security Component, you should have at least PHP 5.4.11 due to PHP bug #63379 (as a workaround, you can also set invalidate_session to false in the security logout handler configuration)', + 'Install PHP 5.4.11 or newer if your project uses the logout handler from the Symfony Security Component.' + ); + + $this->addRecommendation( + (version_compare($installedPhpVersion, '5.3.18', '>=') && version_compare($installedPhpVersion, '5.4.0', '<')) + || + version_compare($installedPhpVersion, '5.4.8', '>='), + 'You should use PHP 5.3.18+ or PHP 5.4.8+ to always get nice error messages for fatal errors in the development environment due to PHP bug #61767/#60909', + 'Install PHP 5.3.18+ or PHP 5.4.8+ if you want nice error messages for all fatal errors in the development environment.' + ); + + if (null !== $pcreVersion) { + $this->addRecommendation( + $pcreVersion >= 8.0, + sprintf('PCRE extension should be at least version 8.0 (%s installed)', $pcreVersion), + 'PCRE 8.0+ is preconfigured in PHP since 5.3.2 but you are using an outdated version of it. Symfony probably works anyway but it is recommended to upgrade your PCRE extension.' + ); + } + + $this->addRecommendation( + class_exists('DomDocument'), + 'PHP-DOM and PHP-XML modules should be installed', + 'Install and enable the PHP-DOM and the PHP-XML modules.' + ); + + $this->addRecommendation( + function_exists('mb_strlen'), + 'mb_strlen() should be available', + 'Install and enable the mbstring extension.' + ); + + $this->addRecommendation( + function_exists('iconv'), + 'iconv() should be available', + 'Install and enable the iconv extension.' + ); + + $this->addRecommendation( + function_exists('utf8_decode'), + 'utf8_decode() should be available', + 'Install and enable the XML extension.' + ); + + $this->addRecommendation( + function_exists('filter_var'), + 'filter_var() should be available', + 'Install and enable the filter extension.' + ); + + if (!defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->addRecommendation( + function_exists('posix_isatty'), + 'posix_isatty() should be available', + 'Install and enable the php_posix extension (used to colorize the CLI output).' + ); + } + + $this->addRecommendation( + extension_loaded('intl'), + 'intl extension should be available', + 'Install and enable the intl extension (used for validators).' + ); + + if (extension_loaded('intl')) { + // in some WAMP server installations, new Collator() returns null + $this->addRecommendation( + null !== new Collator('fr_FR'), + 'intl extension should be correctly configured', + 'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.' + ); + + // check for compatible ICU versions (only done when you have the intl extension) + if (defined('INTL_ICU_VERSION')) { + $version = INTL_ICU_VERSION; + } else { + $reflector = new ReflectionExtension('intl'); + + ob_start(); + $reflector->info(); + $output = strip_tags(ob_get_clean()); + + preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches); + $version = $matches[1]; + } + + $this->addRecommendation( + version_compare($version, '4.0', '>='), + 'intl ICU version should be at least 4+', + 'Upgrade your intl extension with a newer ICU version (4+).' + ); + + $this->addPhpIniRecommendation( + 'intl.error_level', + create_function('$cfgValue', 'return (int) $cfgValue === 0;'), + true, + 'intl.error_level should be 0 in php.ini', + 'Set "intl.error_level" to "0" in php.ini* to inhibit the messages when an error occurs in ICU functions.' + ); + } + + $accelerator = + (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) + || + (extension_loaded('apc') && ini_get('apc.enabled')) + || + (extension_loaded('Zend Optimizer+') && ini_get('zend_optimizerplus.enable')) + || + (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) + || + (extension_loaded('xcache') && ini_get('xcache.cacher')) + || + (extension_loaded('wincache') && ini_get('wincache.ocenabled')) + ; + + $this->addRecommendation( + $accelerator, + 'a PHP accelerator should be installed', + 'Install and/or enable a PHP accelerator (highly recommended).' + ); + + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $this->addRecommendation( + $this->getRealpathCacheSize() >= 5 * 1024 * 1024, + 'realpath_cache_size should be at least 5M in php.ini', + 'Setting "realpath_cache_size" to e.g. "5242880" or "5M" in php.ini* may improve performance on Windows significantly in some cases.' + ); + } + + $this->addPhpIniRecommendation('short_open_tag', false); + + $this->addPhpIniRecommendation('magic_quotes_gpc', false, true); + + $this->addPhpIniRecommendation('register_globals', false, true); + + $this->addPhpIniRecommendation('session.auto_start', false); + + $this->addRecommendation( + class_exists('PDO'), + 'PDO should be installed', + 'Install PDO (mandatory for Doctrine).' + ); + + if (class_exists('PDO')) { + $drivers = PDO::getAvailableDrivers(); + $this->addRecommendation( + count($drivers) > 0, + sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'), + 'Install PDO drivers (mandatory for Doctrine).' + ); + } + } + + /** + * Loads realpath_cache_size from php.ini and converts it to int. + * + * (e.g. 16k is converted to 16384 int) + * + * @return int + */ + protected function getRealpathCacheSize() + { + $size = ini_get('realpath_cache_size'); + $size = trim($size); + $unit = ''; + if (!ctype_digit($size)) { + $unit = strtolower(substr($size, -1, 1)); + $size = (int) substr($size, 0, -1); + } + switch ($unit) { + case 'g': + return $size * 1024 * 1024 * 1024; + case 'm': + return $size * 1024 * 1024; + case 'k': + return $size * 1024; + default: + return (int) $size; + } + } + + /** + * Defines PHP required version from Symfony version. + * + * @return string|false The PHP required version or false if it could not be guessed + */ + protected function getPhpRequiredVersion() + { + if (!file_exists($path = __DIR__.'/../composer.lock')) { + return false; + } + + $composerLock = json_decode(file_get_contents($path), true); + foreach ($composerLock['packages'] as $package) { + $name = $package['name']; + if ('symfony/symfony' !== $name && 'symfony/http-kernel' !== $name) { + continue; + } + + return (int) $package['version'][1] > 2 ? self::REQUIRED_PHP_VERSION : self::LEGACY_REQUIRED_PHP_VERSION; + } + + return false; + } +} diff --git a/app/check.php b/app/check.php new file mode 100644 index 000000000..c6e5a877e --- /dev/null +++ b/app/check.php @@ -0,0 +1,141 @@ +getPhpIniConfigPath(); + +echo_title('Symfony Requirements Checker'); + +echo '> PHP is using the following php.ini file:'.PHP_EOL; +if ($iniPath) { + echo_style('green', ' '.$iniPath); +} else { + echo_style('yellow', ' WARNING: No configuration file (php.ini) used by PHP!'); +} + +echo PHP_EOL.PHP_EOL; + +echo '> Checking Symfony requirements:'.PHP_EOL.' '; + +$messages = array(); +foreach ($symfonyRequirements->getRequirements() as $req) { + if ($helpText = get_error_message($req, $lineSize)) { + echo_style('red', 'E'); + $messages['error'][] = $helpText; + } else { + echo_style('green', '.'); + } +} + +$checkPassed = empty($messages['error']); + +foreach ($symfonyRequirements->getRecommendations() as $req) { + if ($helpText = get_error_message($req, $lineSize)) { + echo_style('yellow', 'W'); + $messages['warning'][] = $helpText; + } else { + echo_style('green', '.'); + } +} + +if ($checkPassed) { + echo_block('success', 'OK', 'Your system is ready to run Symfony projects'); +} else { + echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects'); + + echo_title('Fix the following mandatory requirements', 'red'); + + foreach ($messages['error'] as $helpText) { + echo ' * '.$helpText.PHP_EOL; + } +} + +if (!empty($messages['warning'])) { + echo_title('Optional recommendations to improve your setup', 'yellow'); + + foreach ($messages['warning'] as $helpText) { + echo ' * '.$helpText.PHP_EOL; + } +} + +echo PHP_EOL; +echo_style('title', 'Note'); +echo ' The command console could use a different php.ini file'.PHP_EOL; +echo_style('title', '~~~~'); +echo ' than the one used with your web server. To be on the'.PHP_EOL; +echo ' safe side, please check the requirements from your web'.PHP_EOL; +echo ' server using the '; +echo_style('yellow', 'web/config.php'); +echo ' script.'.PHP_EOL; +echo PHP_EOL; + +exit($checkPassed ? 0 : 1); + +function get_error_message(Requirement $requirement, $lineSize) +{ + if ($requirement->isFulfilled()) { + return; + } + + $errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL; + $errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL; + + return $errorMessage; +} + +function echo_title($title, $style = null) +{ + $style = $style ?: 'title'; + + echo PHP_EOL; + echo_style($style, $title.PHP_EOL); + echo_style($style, str_repeat('~', strlen($title)).PHP_EOL); + echo PHP_EOL; +} + +function echo_style($style, $message) +{ + // ANSI color codes + $styles = array( + 'reset' => "\033[0m", + 'red' => "\033[31m", + 'green' => "\033[32m", + 'yellow' => "\033[33m", + 'error' => "\033[37;41m", + 'success' => "\033[37;42m", + 'title' => "\033[34m", + ); + $supports = has_color_support(); + + echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : ''); +} + +function echo_block($style, $title, $message) +{ + $message = ' '.trim($message).' '; + $width = strlen($message); + + echo PHP_EOL.PHP_EOL; + + echo_style($style, str_repeat(' ', $width).PHP_EOL); + echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT).PHP_EOL); + echo_style($style, str_pad($message, $width, ' ', STR_PAD_RIGHT).PHP_EOL); + echo_style($style, str_repeat(' ', $width).PHP_EOL); +} + +function has_color_support() +{ + static $support; + + if (null === $support) { + if (DIRECTORY_SEPARATOR == '\\') { + $support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); + } else { + $support = function_exists('posix_isatty') && @posix_isatty(STDOUT); + } + } + + return $support; +} diff --git a/app/config/config_framework.yml b/app/config/config_framework.yml index 0dc7bf3c8..e8b844264 100644 --- a/app/config/config_framework.yml +++ b/app/config/config_framework.yml @@ -1,4 +1,11 @@ +#services: +# app.doctrine.apc_cache: +# class: Doctrine\Common\Cache\ApcCache +# calls: +# - [setNamespace, [""]] framework: +# annotations: +# cache: "app.doctrine.apc_cache" #esi: ~ translator: { fallback: en } serializer: { enable_annotations: true } diff --git a/app/config/paramters.php b/app/config/paramters.php new file mode 100644 index 000000000..163f35dd9 --- /dev/null +++ b/app/config/paramters.php @@ -0,0 +1,272 @@ +setParameter('database_driver', 'pdo_mysql'); + +/** + * Specifies the hostname for the database + */ +$container->setParameter('database_host', 'localhost'); +/** + * Specifies the database port. + */ +$container->setParameter('database_port', '3306'); + +/** + * Specifies the database name + */ +$container->setParameter('database_name', 'symfony'); + +/** + * Specifies the username for the database + */ +$container->setParameter('database_user', 'root'); + +/** + * Specifies the password for the database + */ +$container->setParameter('database_password', null); + +//====================================================================================================================== +// Mailer Settings +// Currently not used, the defaults are fine +//====================================================================================================================== + +// The mailer transport. Can be smtp, mail, sendmail or gmail +$container->setParameter('mailer_transport', null); + +// The mail server host name or IP +$container->setParameter('mailer_host', null); + +// The mail server port to use +$container->setParameter('mailer_port', null); + +// The encryption method to use. Can be ssl, tls or null for unencrypted mail transport +$container->setParameter('mailer_encryption', null); + +// The mail server username +$container->setParameter('mailer_user', null); + +// The mail server password +$container->setParameter('mailer_password', null); + +// The mail server auth mode. Can be plain, login or cram-md5 +$container->setParameter('mailer_auth_mode', null); + +//====================================================================================================================== +// Misc framework settings +//====================================================================================================================== + +// The locale to use. Currently only en is supported +$container->setParameter('locale', 'en'); + +// The secret. See http://symfony.com/doc/current/reference/configuration/framework.html#secret +$container->setParameter('secret', 'COAAFJGGLPHPDGGNCNILHFGECFMMACKC'); + +//====================================================================================================================== +// LDAP Configuration +// Example for Active Directory: +// https://github.com/Maks3w/FR3DLdapBundle/blob/master/Resources/doc/cookbook/active-directory.md +//====================================================================================================================== + +// The LDAP Server Host +$container->setParameter('fr3d_ldap.driver.host', '127.0.0.1'); + +// The LDAP Sever Port +$container->setParameter('fr3d_ldap.driver.port', null); + +// The username to use for LDAP queries +$container->setParameter('fr3d_ldap.driver.username', null); + +// The password to use for LDAP queries +$container->setParameter('fr3d_ldap.driver.password', null); + +// true to require a DN for binding attemts, false otherwise +$container->setParameter('fr3d_ldap.driver.bindRequiresDn', false); + +// The base DN to query for users +$container->setParameter('fr3d_ldap.driver.baseDn', ''); + +// sprintf format %s will be the username +$container->setParameter('fr3d_ldap.driver.accountFilterFormat', null); + +$container->setParameter('fr3d_ldap.driver.optReferrals', null); + +// true to use SSL, false otherwise +$container->setParameter('fr3d_ldap.driver.useSsl', null); + +// true to use startTls, false otherwise +$container->setParameter('fr3d_ldap.driver.useStartTls', null); + +// currently not used +$container->setParameter('fr3d_ldap.driver.accountCanonicalForm', null); + +$container->setParameter('fr3d_ldap.driver.accountDomainName', null); +$container->setParameter('fr3d_ldap.driver.accountDomainNameShort', null); + +// set to true to enable LDAP +$container->setParameter('fr3d_ldap.user.enabled', false); + +// sets the base DN +$container->setParameter('fr3d_ldap.user.baseDn', 'dc=blabla,dc=com'); + +// The filter to use for queries +$container->setParameter('fr3d_ldap.user.filter', null); + +// The username attribute +$container->setParameter('fr3d_ldap.user.attribute.username', "samaccountname"); + +// The email attribute +$container->setParameter('fr3d_ldap.user.attribute.email', "email"); + + +//====================================================================================================================== +// PartKeepr settings +//====================================================================================================================== + +// The authentication provider to use. Can be either PartKeepr.Auth.WSSEAuthenticationProvider or +// PartKeepr.Auth.HTTPBasicAuthenticationProvider +$container->setParameter('authentication_provider', 'PartKeepr.Auth.WSSEAuthenticationProvider'); + +/** + * Specifies if the frontend should perform an auto-login + */ +$container->setParameter('partkeepr.frontend.auto_login.enabled', false); + +/** + * Specifies the auto-login username + */ +$container->setParameter('partkeepr.frontend.auto_login.username', 'admin'); + +/** + * Specifies the auto-login password + */ +$container->setParameter('partkeepr.frontend.auto_login.password', 'admin'); + +/** + * Specifies the base_url for the PartKeepr frontend. + * Usually this is not required, but if you run PartKeepr behind a reverse + * proxy with a different path, you can set it here. + * + * Please note that you need to create an additional file, see + * https://wiki.partkeepr.org/wiki/KB00008:PartKeepr_behind_a_reverse_proxy + * + * Example: If PartKeepr runs on / within a docker container and your reverse + * proxy maps it on https://www.example.org/parts, you can set the + * base_url to https://www.example.org/parts + */ +$container->setParameter('partkeepr.frontend.base_url', false); + +/** + * Specifies the category path separator + */ +$container->setParameter('partkeepr.category.path_separator', ' ➤ '); + +/** + * Specifies a message of the day. Set to any string instead of false + * to display a MOTD. Example + * $container->setParameter('partkeepr.frontend.motd', "This is a MOTD"); + */ +$container->setParameter('partkeepr.frontend.motd', false); + +/** + * Specifies if a quota should be used. + * If set to false, no quota is used. Set it to a numeric value to set a quota in bytes. + */ +$container->setParameter('partkeepr.filesystem.quota', false); + +/** + * Specifies the dunglas cache. Defaults to false. + * You can use the APCu cache by specifying "api.mapping.cache.apc" here. + * + * Further reading: https://api-platform.com/doc/1.0/api-bundle/performances + */ +$container->setParameter('cache.dunglas', false); + +/** + * Specifies the doctrine cache. Defaults to "array", but can be "apc". + * + * Further reading: http://symfony.com/doc/current/bundles/DoctrineBundle/configuration.html#caching-drivers + * + * For complex caching scenarios, you are advised to use a custom configuration file as described at the top of this + * file. + */ +$container->setParameter('cache.doctrine', 'array'); + +/** + * Defines if a maintenance page should be displayed. + */ +$container->setParameter('partkeepr.maintenance', false); + +/** + * Defines if a maintenance page should be displayed. Set to false to prevent a maintenance page being + * displayed, or to a string which should occur on the maintenance page. + */ +$container->setParameter('partkeepr.maintenance.title', ''); + +/** + * Defines if a maintenance page should be displayed. Set to false to prevent a maintenance page being + * displayed, or to a string which should occur on the maintenance page. + */ +$container->setParameter('partkeepr.maintenance.message', ''); + +/** + * Defines a limit for the maximum amount of users allowed. Valid values are false (no limit) or an integer number + */ +$container->setParameter('partkeepr.users.limit', false); + +/** + * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number + */ +$container->setParameter('partkeepr.parts.limit', false); + +/** + * Defines if the internal part number must be unique or not. Note that empty internal part numbers aren't checked - + * if you require to enforce an internal part number, also set the field internalPartNumber to mandatory. + * + * Defaults to false + */ +$container->setParameter('partkeepr.parts.internalpartnumberunique', false); + +/** + * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number + */ +$container->setParameter('partkeepr.upload.limit', false); + +/** + * Specifies the PartKeepr data directory + */ +$container->setParameter('partkeepr.filesystem.data_directory', '%kernel.root_dir%/../data/'); + +/** + * Specifies if PartKeepr should check for non-running cronjobs + */ +$container->setParameter('partkeepr.cronjob.check', true); + +/** + * Specifies which API key PartKeepr should use to talk to OctoPart. You can get an API key by registering at + * https://octopart.com/api/home and then registering an application. + */ +$container->setParameter('partkeepr.octopart.apikey', ''); + +/** + * Specifies which URL contains the patreon status. If you do not wish to display the patreon status, + * set this parameter to false. Please note that we rely on your Patreon pledges to ensure further + * development of PartKeepr. + */ +$container->setParameter('partkeepr.patreon.statusuri', 'https://www.partkeepr.org/patreon.json'); \ No newline at end of file diff --git a/app/logs/.htaccess b/app/logs/.htaccess deleted file mode 100644 index 93169e4eb..000000000 --- a/app/logs/.htaccess +++ /dev/null @@ -1,2 +0,0 @@ -Order deny,allow -Deny from all diff --git a/app/logs/ignore.json b/app/logs/ignore.json deleted file mode 100644 index 3481b8db9..000000000 --- a/app/logs/ignore.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "readable" -} diff --git a/composer.json b/composer.json index 955899c79..c008a87c2 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,6 @@ "symfony/assetic-bundle": "~2.8.2", "symfony/swiftmailer-bundle": "~2.3", "symfony/monolog-bundle": "~2.4", - "sensio/distribution-bundle": "~4.0.0", "sensio/framework-extra-bundle": "~3.0", "nelmio/api-doc-bundle": "~2.9@dev", "friendsofsymfony/rest-bundle": "~1.7.1", @@ -77,7 +76,8 @@ "phpseclib/phpseclib": "~2.0", "snc/redis-bundle": "^1.1", "predis/predis": "^1.0", - "guzzlehttp/guzzle": "6.2.2" + "guzzlehttp/guzzle": "6.2.2", + "sensio/distribution-bundle": "4.0.0" }, "require-dev": { "phpunit/phpunit": "5.5", diff --git a/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css b/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css index e2a91a0dd..0d1de9d7e 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css +++ b/src/PartKeepr/FrontendBundle/Resources/public/css/PartKeepr.css @@ -233,4 +233,4 @@ margin-left: -75px; border: 1px solid #b8daff; border-radius: .25rem; padding: .25rem .75rem; -} \ No newline at end of file +} diff --git a/src/PartKeepr/FrontendBundle/Resources/public/images/become_a_patron_button.xcf b/src/PartKeepr/FrontendBundle/Resources/public/images/become_a_patron_button.xcf new file mode 100644 index 0000000000000000000000000000000000000000..e1e3cfff098207357dfd9729355faa502261ce4b GIT binary patch literal 8721 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 = $price; + if($price != 0) + $this->averagePrice = $price; } /** @@ -784,6 +785,10 @@ public function onPreUpdate() public function addStockLevel(StockEntry $stockEntry) { $stockEntry->setPart($this); + + if($this->getAveragePrice() != 0) + $stockEntry->setPrice($this->getAveragePrice()); + $this->stockLevels->add($stockEntry); } diff --git a/src/PartKeepr/StockBundle/Entity/StockEntry.php b/src/PartKeepr/StockBundle/Entity/StockEntry.php index aba8f4484..32d6d9df7 100644 --- a/src/PartKeepr/StockBundle/Entity/StockEntry.php +++ b/src/PartKeepr/StockBundle/Entity/StockEntry.php @@ -213,7 +213,7 @@ public function getUser() public function checkPrice() { if ($this->getStockLevel() < 0 && $this->getPrice() !== null) { - $this->setPrice(null); + //$this->setPrice(null); } } diff --git a/web/phpinfo.php b/web/phpinfo.php new file mode 100644 index 000000000..a4d275df4 --- /dev/null +++ b/web/phpinfo.php @@ -0,0 +1,6 @@ + From aa300bbc9b2377bbce90dddbf3f73c6c96752b85 Mon Sep 17 00:00:00 2001 From: RezaMohammadi99 Date: Wed, 8 May 2019 15:55:36 +0000 Subject: [PATCH 02/13] Fixed prices in stock history. This commit adds the part price information to the stock history. The average price of a part doesn't change when stock is depleted From ddd3c79eea80b3cb28819579305802f36d559833 Mon Sep 17 00:00:00 2001 From: RezaMohammadi99 Date: Mon, 13 May 2019 15:26:09 +0000 Subject: [PATCH 03/13] Root category not set as default. This commit sets the default category to null upon part creation. This is in effort to make the user pick the correct category. --- .../public/js/Components/Part/Editor/PartEditor.js | 3 +++ .../Resources/public/js/Components/Part/PartsManager.js | 2 +- .../public/js/Components/Project/ProjectReport.js | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartEditor.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartEditor.js index ee6b0b6b6..2dc097791 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartEditor.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartEditor.js @@ -119,7 +119,9 @@ Ext.define('PartKeepr.PartEditor', { }, { xtype: 'CategoryComboBox', fieldLabel: i18n("Category"), + fieldClass: '', name: 'category', + allowBlank: false, displayField: "name", returnObject: true }, @@ -400,6 +402,7 @@ Ext.define('PartKeepr.PartEditor', { Ext.String.format(i18n("The number of attachments must be greater than {0}"), minAttachmentCount)); } + // Force footprint to be "null" when the checkbox is checked. if (this.footprintNone.getValue() === true) { this.record.setFootprint(null); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js index 48e48a372..5b1b4c3b7 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsManager.js @@ -498,7 +498,7 @@ Ext.define('PartKeepr.PartManager', { record.setCategory(this.getSelectedCategory()); } else { - record.setCategory(this.tree.getRootNode().firstChild); + //record.setCategory(this.tree.getRootNode().firstChild); } record.setPartUnit(defaultPartUnit); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js index b656671c9..693f98fcd 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js @@ -151,8 +151,11 @@ Ext.define('PartKeepr.ProjectReportView', { success: this.onProjectReportLoaded, scope: this }); - - this.reportList.getStore().reload(); + + + + + }, onProjectReportLoaded: function () { this.reportResult.reconfigure(this.projectReport.reportParts()); From 2e1c8fa6cf4c67ae734d71d6f853fdae74e0b7e4 Mon Sep 17 00:00:00 2001 From: RezaMohammadi99 Date: Tue, 4 Jun 2019 18:21:33 +0000 Subject: [PATCH 04/13] Fixed Exporting Issue This commit fixes the exporter adding accented characters to the file. --- .../js/Components/Exporter/GridExporter.js | 7 ++++++- .../js/Components/Project/MetaPartSubgrid.js | 9 +++++---- .../js/Components/Project/ProjectReport.js | 7 +++++-- .../Project/Renderers/RemarksRenderer.js | 1 + .../ProjectBundle/Entity/ReportPart.php | 17 +++++++++++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Exporter/GridExporter.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Exporter/GridExporter.js index ee8064fdd..7e5efe54c 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Exporter/GridExporter.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Exporter/GridExporter.js @@ -50,7 +50,12 @@ Ext.define("PartKeepr.Exporter.GridExporter", { } if (!column.isHidden()) { - rowValues.push(Ext.util.Format.stripTags(value)); + try{ + rowValues.push(Ext.util.Format.stripTags(value.replace(/[^\x1F-\x7D]/g,''))) + } + catch(err){ + rowValues.push(Ext.util.Format.stripTags(value)); + } } } diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js index 96f9bb8cb..be3a0e229 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js @@ -85,7 +85,6 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { onApplyMetaPartsClick: function (button) { var parentRecord = button.up("grid").parentRecord; - this.convertMetaPartsToParts(parentRecord); }, /** @@ -98,7 +97,7 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { { var missing; - var i, projectReportItem, subPart; + var i, projectReportItem, subPart, projectPart; for (i = 0; i < record.subParts().getCount(); i++) { @@ -119,7 +118,9 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { projectReportItem.set("quantity", subPart.get("stockToUse")); projectReportItem.setReport(this.up("#projectReportResult").projectReport); - + projectPart = Ext.create("PartKeepr.ProjectBundle.Entity.ProjectPart"); + projectPart.setPart(subPart); + projectPart.set("remarks", "remark"); record.store.add(projectReportItem); } } @@ -192,4 +193,4 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { return total; } -}); \ No newline at end of file +}); diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js index 693f98fcd..a1ebfe36f 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReport.js @@ -108,7 +108,7 @@ Ext.define('PartKeepr.ProjectReportView', { quantity: projectsToReport[i].quantity })); } - + this.doSaveProjectReport(); }, /** @@ -130,7 +130,6 @@ Ext.define('PartKeepr.ProjectReportView', { { this.reportResult.setProjectsToReport([]); this.reportResult.setStore(new Ext.data.Store()); - var selection = this.reportList.getSelection(); if (selection.length === 1) { @@ -151,10 +150,14 @@ Ext.define('PartKeepr.ProjectReportView', { success: this.onProjectReportLoaded, scope: this }); + + + + }, onProjectReportLoaded: function () { diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js index a3aada78b..2ed1582ae 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js @@ -7,6 +7,7 @@ Ext.define("PartKeepr.Components.ProjectReport.Renderers.RemarksRenderer", { return renderObj.getProjectParts(record); }, getProjectParts: function (rec) { + var report = rec.getReport(), i, j, project, projectPart, projectPartQuantities = []; diff --git a/src/PartKeepr/ProjectBundle/Entity/ReportPart.php b/src/PartKeepr/ProjectBundle/Entity/ReportPart.php index 15595b74a..fea37675b 100644 --- a/src/PartKeepr/ProjectBundle/Entity/ReportPart.php +++ b/src/PartKeepr/ProjectBundle/Entity/ReportPart.php @@ -42,6 +42,8 @@ class ReportPart extends BaseEntity * @var int */ private $quantity; + + private $remarks; /** * @ORM\ManyToOne(targetEntity="PartKeepr\DistributorBundle\Entity\Distributor") @@ -336,6 +338,21 @@ public function setPart($part) return $this; } + + // remark getter + public function getRemarks() + { + return $this->remarks; + } + + //remark setter + public function setRemarks($remarks) + { + $this->remarks = $remarks; + + return $this; + } + public function __toString() { From 7eace5c569847254c3f40c02206a2c98cf32b3fb Mon Sep 17 00:00:00 2001 From: RezaMohammadi99 Date: Thu, 20 Jun 2019 16:41:21 +0000 Subject: [PATCH 05/13] Fixed Project Report Remarks This commit keeps the project remark connected to the newly selected items in a project report. --- Profile | 0 .../js/Components/Project/MetaPartSubgrid.js | 15 ++++++++----- .../Project/ProjectReportResultGrid.js | 2 +- .../Project/Renderers/RemarksRenderer.js | 22 +++++++++++++++---- .../Resources/public/js/PartKeepr.js | 2 +- src/PartKeepr/PartBundle/Entity/Part.php | 1 + 6 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 Profile diff --git a/Profile b/Profile new file mode 100644 index 000000000..e69de29bb diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js index be3a0e229..b541095da 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/MetaPartSubgrid.js @@ -85,6 +85,7 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { onApplyMetaPartsClick: function (button) { var parentRecord = button.up("grid").parentRecord; + this.convertMetaPartsToParts(parentRecord); }, /** @@ -97,7 +98,7 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { { var missing; - var i, projectReportItem, subPart, projectPart; + var i, projectReportItem, subPart; for (i = 0; i < record.subParts().getCount(); i++) { @@ -112,15 +113,17 @@ Ext.define('PartKeepr.Components.Project.MetaPartSubgrid', { } else { missing = Math.abs(missing); } - + + if(subPart.get("comment").indexOf("DO NOT CHANGE") == -1) + subPart.set("comment", subPart.get("comment") + "\nDO NOT CHANGE:" + record.data.report + record._part.data.name); + else if(subPart.get("comment").indexOf(record.data.report) != -1) + subPart.set("comment", subPart.get("comment") + record._part.data.name); + else + subPart.set("comment", subPart.get("comment").slice(0,subPart.get("comment").indexOf("DO NOT CHANGE")+14) + record.data.report + record._part.data.name); projectReportItem = Ext.create("PartKeepr.ProjectBundle.Entity.ReportPart"); projectReportItem.setPart(subPart); projectReportItem.set("quantity", subPart.get("stockToUse")); projectReportItem.setReport(this.up("#projectReportResult").projectReport); - - projectPart = Ext.create("PartKeepr.ProjectBundle.Entity.ProjectPart"); - projectPart.setPart(subPart); - projectPart.set("remarks", "remark"); record.store.add(projectReportItem); } } diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReportResultGrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReportResultGrid.js index 440448299..ab707d03d 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReportResultGrid.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/ProjectReportResultGrid.js @@ -355,7 +355,7 @@ Ext.define("PartKeepr.Components.Project.ProjectReportResultGrid", { amount: item.get("quantity"), comment: item.getReport().reportProjects().getFieldValues("project.name").join(", "), lotNumber: item.projectParts().getFieldValues("lotNumber").join(", "), - projects: [] // item.getReport().reportProjects() + projects: [] }); } diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js index 2ed1582ae..63b289854 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Project/Renderers/RemarksRenderer.js @@ -9,16 +9,17 @@ Ext.define("PartKeepr.Components.ProjectReport.Renderers.RemarksRenderer", { getProjectParts: function (rec) { var report = rec.getReport(), - i, j, project, projectPart, projectPartQuantities = []; + i, j, k, project, projectPart, projectPartQuantities = []; for (i = 0; i < report.reportProjects().getCount(); i++) { project = report.reportProjects().getAt(i).getProject(); - + for (j = 0; j < project.parts().getCount(); j++) { projectPart = project.parts().getAt(j); - + + if (projectPart.getPart().getId() === rec.getPart().getId()) { if (projectPart.get("remarks") !== "" && projectPart.get("remarks") !== null) @@ -26,9 +27,22 @@ Ext.define("PartKeepr.Components.ProjectReport.Renderers.RemarksRenderer", { projectPartQuantities.push(project.get("name") + ": " + projectPart.get("remarks")); } } + else + { + + if (rec.getPart().data.comment.includes(projectPart.getPart().data.name)) + { + if (projectPart.get("remarks") !== "" && projectPart.get("remarks") !== null) + { + projectPartQuantities.push(project.get("name") + ": " + projectPart.get("remarks")); + } + } + + } + } } - + return projectPartQuantities.join(" ") }, diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js b/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js index e56cecc72..ae1280dba 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/PartKeepr.js @@ -233,7 +233,7 @@ Ext.application({ } if (data.inactiveCronjobCount > 0) { - alert(i18n("The following cronjobs aren't running:") + "\n\n" + data.inactiveCronjobs.join("\n")); + //alert(i18n("The following cronjobs aren't running:") + "\n\n" + data.inactiveCronjobs.join("\n")); } }, /* diff --git a/src/PartKeepr/PartBundle/Entity/Part.php b/src/PartKeepr/PartBundle/Entity/Part.php index 375697038..b943bd4ca 100644 --- a/src/PartKeepr/PartBundle/Entity/Part.php +++ b/src/PartKeepr/PartBundle/Entity/Part.php @@ -27,6 +27,7 @@ */ class Part extends BaseEntity { + private $origin; /** * The category of the part. * From 45f6c9bce8036f036be91f1f0845d6a5fcacc41f Mon Sep 17 00:00:00 2001 From: Jop Huttenhuis Date: Mon, 3 Sep 2018 16:01:37 +0200 Subject: [PATCH 06/13] Fixes 997: Duplicate expand button changed to collapse button --- .../Resources/public/js/Components/Part/PartsGrid.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js index 411527d98..82ce01d1e 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js @@ -115,11 +115,11 @@ Ext.define('PartKeepr.PartsGrid', { this.bottomToolbar.add({ xtype: 'button', - tooltip: i18n("Expand all Groups"), - iconCls: this.expandRowButtonIconCls, + tooltip: i18n("Collapse all Groups"), + iconCls: this.collapseRowButtonIconCls, listeners: { scope: this.groupingFeature, - click: this.groupingFeature.expandAll + click: this.groupingFeature.collapseAll } }); From e6bb6adcb58f3504a10b6dbad26c4b8ab2a6018a Mon Sep 17 00:00:00 2001 From: Drannor Dosalith <20868397+Drannor-Dosalith@users.noreply.github.com> Date: Tue, 7 Aug 2018 17:01:21 -0400 Subject: [PATCH 07/13] Check if the bcscale function exists, to validate if BCMath PHP library is available. --- app/PartKeeprRequirements.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/PartKeeprRequirements.php b/app/PartKeeprRequirements.php index 2a0f56626..566a2b4a3 100644 --- a/app/PartKeeprRequirements.php +++ b/app/PartKeeprRequirements.php @@ -59,6 +59,12 @@ function_exists('mb_convert_case'), sprintf('Please compile PHP with the mbstring functions in case you are using Gentoo, or install php-mbstring on RedHat, Fedora or CentOS.') ); + $this->addRequirement( + function_exists('bcscale'), + sprintf('BCMath library not found'), + sprintf('Install the BCMath library extension') + ); + if (ini_get('opcache.enable')) { if (version_compare(phpversion(), '7.0', '<')) { $this->addPhpIniRequirement('opcache.save_comments', 1, From bb9d0fc77af2cd398cc03e8066b0f4c6727c1d2b Mon Sep 17 00:00:00 2001 From: Florian Kerle Date: Tue, 31 Jul 2018 23:15:22 +0200 Subject: [PATCH 08/13] fix #989: parameter info lost, selecting existing parameter * populate all form-items with values from selected parameter-record `onParameterSelect(...)` * normalize order of properties (list unit name after id) Signed-off-by: Florian Kerle --- .../Part/Editor/PartParameterValueEditor.js | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartParameterValueEditor.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartParameterValueEditor.js index 5aa5bfb6c..61bfcc59f 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartParameterValueEditor.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/Editor/PartParameterValueEditor.js @@ -17,14 +17,15 @@ Ext.define("PartKeepr.PartParameterValueEditor", { { fieldLabel: i18n("Description"), name: 'description', + itemId: 'description', xtype: 'textarea' }, { xtype: 'UnitComboBox', fieldLabel: i18n("Unit"), + name: 'unit', itemId: "unit", - returnObject: true, - name: 'unit' + returnObject: true }, { fieldLabel: i18n("Value Type"), @@ -111,6 +112,11 @@ Ext.define("PartKeepr.PartParameterValueEditor", { }, onPartParameterSelect: function (combo, record) { + var description = record.get("description"); + if (description !== null) { + this.down("#description").setRawValue(description); + } + if (record.get("unitName") !== null) { var unit = this.down("#unit").getStore().findRecord("name", record.get("unitName"), 0, false, true, true); @@ -118,7 +124,19 @@ Ext.define("PartKeepr.PartParameterValueEditor", { this.down("#unit").select(unit); this.down("#valueType").setValue({valueType: "numeric"}); } + + } else { + this.down("#unit").select(null); } + + var valueType = record.get("valueType"); + if (valueType == "numeric") { + this.down("#valueType").setValue({valueType: "numeric"}); + + } else if (valueType == "string") { + this.down("#valueType").setValue({valueType: "string"}); + } + }, onUnitChange: function (combo, newValue) { var prefixes,j, unitFilter = []; From 71e4e5db8dd01596d2d731e02beda8f03667adb3 Mon Sep 17 00:00:00 2001 From: Jop Huttenhuis Date: Thu, 11 Oct 2018 15:05:21 +0200 Subject: [PATCH 09/13] Closes #418 - Doubleclick storage location This commit closes issue #418. Double clicking on a part-item in a 'Storage Location' opens the part details window. --- .../StorageLocation/StorageLocationEditor.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js index bfddff88d..21c521dbb 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/StorageLocation/StorageLocationEditor.js @@ -48,6 +48,8 @@ Ext.define('PartKeepr.StorageLocationEditor', { ] }); + this.gridPanel.on("itemdblclick", this.onDoubleClick, this); + var container = Ext.create("Ext.form.FieldContainer", { fieldLabel: i18n("Contained Parts"), labelWidth: 110, @@ -129,5 +131,27 @@ Ext.define('PartKeepr.StorageLocationEditor', { this.down('#image').setValue(this.record.getImage()); + }, + onDoubleClick: function(view, record) { + if (record) { + this.onEditPart(record); + } + }, + onEditPart: function(part) { + var editorWindow; + + if (part.get("metaPart") === true) + { + editorWindow = Ext.create("PartKeepr.Components.Part.Editor.MetaPartEditorWindow"); + } else + { + editorWindow = Ext.create("PartKeepr.PartEditorWindow"); + } + editorWindow.on("partSaved", this.onPartSaved, this); + editorWindow.editor.editItem(part); + editorWindow.show(); + }, + onPartSaved: function() { + this.grid.getStore().reload(); } }); From 045bd0d22e0e1a375f646caf200c45e8e5f76059 Mon Sep 17 00:00:00 2001 From: Florian Knodt Date: Sat, 27 Oct 2018 22:11:21 +0200 Subject: [PATCH 10/13] PartKeeprRequirements/returnBytes: No math on String --- app/PartKeeprRequirements.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/PartKeeprRequirements.php b/app/PartKeeprRequirements.php index 566a2b4a3..a2041c604 100644 --- a/app/PartKeeprRequirements.php +++ b/app/PartKeeprRequirements.php @@ -123,20 +123,23 @@ protected function returnBytes($val) { $val = trim($val); $last = strtolower($val[strlen($val) - 1]); + $vali = (int)substr($val, 0, -1); switch ($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': - $val *= 1073741824; + $vali *= 1073741824; break; case 'm': - $val *= 1048576; + $vali *= 1048576; break; case 'k': - $val *= 1024; + $vali *= 1024; break; + default: + $vali = (int)$val; } - return $val; + return $vali; } /** From 35ede5dbe6db514f31836c094f7640045ad65718 Mon Sep 17 00:00:00 2001 From: Thomas Nilsson Date: Mon, 29 Oct 2018 17:40:02 +0100 Subject: [PATCH 11/13] Closes #1002 (before it also effects Chrome) Do not rely on deprecated the URL.createObjectURL for MediaStream, other than as a fallback for old browsers. Firefox (62+) have deprecated it, Safari have deprecated it, and Chrome have started the process to deprecate this as well. I should note that I have not built this code myself and tested it, but the issue partkeepr#1002 is still present in the demo site and this code here is simply adopted from the developer site of Mozilla. Sources: https://bugs.webkit.org/show_bug.cgi?id=167518 https://bugs.chromium.org/p/chromium/issues/detail?id=800767#c28 https://www.fxsitecompat.com/en-CA/docs/2018/url-createobjecturl-no-longer-accepts-mediastream-as-argument/ https://developer.mozilla.org/sv-SE/docs/Web/API/HTMLMediaElement/srcObject#Supporting_fallback_to_the_src_property --- .../Resources/public/js/Components/Widgets/WebcamPanel.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/WebcamPanel.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/WebcamPanel.js index 2c43af859..bb9f66e7c 100644 --- a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/WebcamPanel.js +++ b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Widgets/WebcamPanel.js @@ -49,7 +49,11 @@ Ext.define('PartKeepr.WebcamPanel', { }, handleVideo: function (stream) { this.stream = stream; - this.video.src = window.URL.createObjectURL(stream); + try { + this.video.srcObject = stream; + } catch (error) { + this.video.src = window.URL.createObjectURL(stream); + } }, videoError: function () { // @todo: Implement video error handler From 1229a94dca0907fdacfbc69384698ca2c6cb1249 Mon Sep 17 00:00:00 2001 From: Victor Wollesen Date: Mon, 9 Sep 2019 23:25:11 +0000 Subject: [PATCH 12/13] STYLE: Applying styleguide fixes. --- app/PartKeeprRequirements.php | 28 ++++++++-------- app/SymfonyRequirements.php | 17 +++++----- app/check.php | 18 +++++----- app/config/paramters.php | 33 +++++++++---------- src/PartKeepr/PartBundle/Entity/Part.php | 12 ++++--- .../ProjectBundle/Entity/ReportPart.php | 9 +++-- web/phpinfo.php | 2 -- 7 files changed, 59 insertions(+), 60 deletions(-) diff --git a/app/PartKeeprRequirements.php b/app/PartKeeprRequirements.php index a2041c604..9526bded8 100644 --- a/app/PartKeeprRequirements.php +++ b/app/PartKeeprRequirements.php @@ -35,9 +35,9 @@ function_exists('curl_init'), sprintf('The php.ini memory_limit directive must be set to 128MB or higher. Your limit is set to %s', ini_get('memory_limit'))); - $this->checkWritable(realpath(dirname(__FILE__) . '/../data/')); - $this->checkWritable(realpath(dirname(__FILE__) . '/../app/')); - $this->checkWritable(realpath(dirname(__FILE__) . '/../web/')); + $this->checkWritable(realpath(dirname(__FILE__).'/../data/')); + $this->checkWritable(realpath(dirname(__FILE__).'/../app/')); + $this->checkWritable(realpath(dirname(__FILE__).'/../web/')); $this->addRecommendation( function_exists('apc_fetch'), @@ -109,7 +109,7 @@ protected function checkWritable($path) */ protected function getBytesIniSetting($setting) { - return (int)$this->returnBytes(ini_get($setting)); + return (int) $this->returnBytes(ini_get($setting)); } /** @@ -123,7 +123,7 @@ protected function returnBytes($val) { $val = trim($val); $last = strtolower($val[strlen($val) - 1]); - $vali = (int)substr($val, 0, -1); + $vali = (int) substr($val, 0, -1); switch ($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': @@ -136,7 +136,7 @@ protected function returnBytes($val) $vali *= 1024; break; default: - $vali = (int)$val; + $vali = (int) $val; } return $vali; @@ -154,24 +154,26 @@ protected function returnBytes($val) protected function isWritableRecursive($dir) { if (!is_writable($dir)) { - throw new \Exception($dir . ' is not writable.'); + throw new \Exception($dir.' is not writable.'); } $folder = opendir($dir); while ($file = readdir($folder)) { if ($file != '.' && $file != '..') { - if (!is_writable($dir . '/' . $file)) { + if (!is_writable($dir.'/'.$file)) { closedir($folder); - throw new \Exception($dir . '/' . $file . ' is not writable.'); + + throw new \Exception($dir.'/'.$file.' is not writable.'); } else { // Skip hidden directories - if ((is_dir($dir . '/' . $file)) && ($file[0] == '.')) { + if ((is_dir($dir.'/'.$file)) && ($file[0] == '.')) { continue; } - if (is_dir($dir . '/' . $file)) { - if (!$this->isWritableRecursive($dir . '/' . $file)) { + if (is_dir($dir.'/'.$file)) { + if (!$this->isWritableRecursive($dir.'/'.$file)) { closedir($folder); - throw new \Exception($dir . '/' . $file . ' is not writable.'); + + throw new \Exception($dir.'/'.$file.' is not writable.'); } } } diff --git a/app/SymfonyRequirements.php b/app/SymfonyRequirements.php index b21edde67..33eb42b97 100644 --- a/app/SymfonyRequirements.php +++ b/app/SymfonyRequirements.php @@ -171,7 +171,7 @@ class RequirementCollection implements IteratorAggregate /** * @var Requirement[] */ - private $requirements = array(); + private $requirements = []; /** * Gets the current RequirementCollection as an Iterator. @@ -260,7 +260,7 @@ public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsenc * * @param RequirementCollection $collection A RequirementCollection instance */ - public function addCollection(RequirementCollection $collection) + public function addCollection(self $collection) { $this->requirements = array_merge($this->requirements, $collection->all()); } @@ -282,7 +282,7 @@ public function all() */ public function getRequirements() { - $array = array(); + $array = []; foreach ($this->requirements as $req) { if (!$req->isOptional()) { $array[] = $req; @@ -299,7 +299,7 @@ public function getRequirements() */ public function getFailedRequirements() { - $array = array(); + $array = []; foreach ($this->requirements as $req) { if (!$req->isFulfilled() && !$req->isOptional()) { $array[] = $req; @@ -316,7 +316,7 @@ public function getFailedRequirements() */ public function getRecommendations() { - $array = array(); + $array = []; foreach ($this->requirements as $req) { if ($req->isOptional()) { $array[] = $req; @@ -333,7 +333,7 @@ public function getRecommendations() */ public function getFailedRecommendations() { - $array = array(); + $array = []; foreach ($this->requirements as $req) { if (!$req->isFulfilled() && $req->isOptional()) { $array[] = $req; @@ -446,7 +446,7 @@ public function __construct() ); if (false !== $requiredPhpVersion && version_compare($installedPhpVersion, $requiredPhpVersion, '>=')) { - $timezones = array(); + $timezones = []; foreach (DateTimeZone::listAbbreviations() as $abbreviations) { foreach ($abbreviations as $abbreviation) { $timezones[$abbreviation['timezone_id']] = true; @@ -711,8 +711,7 @@ function_exists('posix_isatty'), || (extension_loaded('xcache') && ini_get('xcache.cacher')) || - (extension_loaded('wincache') && ini_get('wincache.ocenabled')) - ; + (extension_loaded('wincache') && ini_get('wincache.ocenabled')); $this->addRecommendation( $accelerator, diff --git a/app/check.php b/app/check.php index c6e5a877e..234d32712 100644 --- a/app/check.php +++ b/app/check.php @@ -19,7 +19,7 @@ echo '> Checking Symfony requirements:'.PHP_EOL.' '; -$messages = array(); +$messages = []; foreach ($symfonyRequirements->getRequirements() as $req) { if ($helpText = get_error_message($req, $lineSize)) { echo_style('red', 'E'); @@ -98,15 +98,15 @@ function echo_title($title, $style = null) function echo_style($style, $message) { // ANSI color codes - $styles = array( - 'reset' => "\033[0m", - 'red' => "\033[31m", - 'green' => "\033[32m", - 'yellow' => "\033[33m", - 'error' => "\033[37;41m", + $styles = [ + 'reset' => "\033[0m", + 'red' => "\033[31m", + 'green' => "\033[32m", + 'yellow' => "\033[33m", + 'error' => "\033[37;41m", 'success' => "\033[37;42m", - 'title' => "\033[34m", - ); + 'title' => "\033[34m", + ]; $supports = has_color_support(); echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : ''); diff --git a/app/config/paramters.php b/app/config/paramters.php index 163f35dd9..0c1d9d7dd 100644 --- a/app/config/paramters.php +++ b/app/config/paramters.php @@ -14,12 +14,12 @@ /** * Specifies the database driver. Available options are listed on this page: - * http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#driver + * http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#driver. */ $container->setParameter('database_driver', 'pdo_mysql'); /** - * Specifies the hostname for the database + * Specifies the hostname for the database. */ $container->setParameter('database_host', 'localhost'); /** @@ -28,17 +28,17 @@ $container->setParameter('database_port', '3306'); /** - * Specifies the database name + * Specifies the database name. */ $container->setParameter('database_name', 'symfony'); /** - * Specifies the username for the database + * Specifies the username for the database. */ $container->setParameter('database_user', 'root'); /** - * Specifies the password for the database + * Specifies the password for the database. */ $container->setParameter('database_password', null); @@ -134,7 +134,6 @@ // The email attribute $container->setParameter('fr3d_ldap.user.attribute.email', "email"); - //====================================================================================================================== // PartKeepr settings //====================================================================================================================== @@ -144,17 +143,17 @@ $container->setParameter('authentication_provider', 'PartKeepr.Auth.WSSEAuthenticationProvider'); /** - * Specifies if the frontend should perform an auto-login + * Specifies if the frontend should perform an auto-login. */ $container->setParameter('partkeepr.frontend.auto_login.enabled', false); /** - * Specifies the auto-login username + * Specifies the auto-login username. */ $container->setParameter('partkeepr.frontend.auto_login.username', 'admin'); /** - * Specifies the auto-login password + * Specifies the auto-login password. */ $container->setParameter('partkeepr.frontend.auto_login.password', 'admin'); @@ -173,14 +172,14 @@ $container->setParameter('partkeepr.frontend.base_url', false); /** - * Specifies the category path separator + * Specifies the category path separator. */ $container->setParameter('partkeepr.category.path_separator', ' ➤ '); /** * Specifies a message of the day. Set to any string instead of false * to display a MOTD. Example - * $container->setParameter('partkeepr.frontend.motd', "This is a MOTD"); + * $container->setParameter('partkeepr.frontend.motd', "This is a MOTD");. */ $container->setParameter('partkeepr.frontend.motd', false); @@ -226,12 +225,12 @@ $container->setParameter('partkeepr.maintenance.message', ''); /** - * Defines a limit for the maximum amount of users allowed. Valid values are false (no limit) or an integer number + * Defines a limit for the maximum amount of users allowed. Valid values are false (no limit) or an integer number. */ $container->setParameter('partkeepr.users.limit', false); /** - * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number + * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number. */ $container->setParameter('partkeepr.parts.limit', false); @@ -244,17 +243,17 @@ $container->setParameter('partkeepr.parts.internalpartnumberunique', false); /** - * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number + * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number. */ $container->setParameter('partkeepr.upload.limit', false); /** - * Specifies the PartKeepr data directory + * Specifies the PartKeepr data directory. */ $container->setParameter('partkeepr.filesystem.data_directory', '%kernel.root_dir%/../data/'); /** - * Specifies if PartKeepr should check for non-running cronjobs + * Specifies if PartKeepr should check for non-running cronjobs. */ $container->setParameter('partkeepr.cronjob.check', true); @@ -269,4 +268,4 @@ * set this parameter to false. Please note that we rely on your Patreon pledges to ensure further * development of PartKeepr. */ -$container->setParameter('partkeepr.patreon.statusuri', 'https://www.partkeepr.org/patreon.json'); \ No newline at end of file +$container->setParameter('partkeepr.patreon.statusuri', 'https://www.partkeepr.org/patreon.json'); diff --git a/src/PartKeepr/PartBundle/Entity/Part.php b/src/PartKeepr/PartBundle/Entity/Part.php index b943bd4ca..6203d94b1 100644 --- a/src/PartKeepr/PartBundle/Entity/Part.php +++ b/src/PartKeepr/PartBundle/Entity/Part.php @@ -163,7 +163,7 @@ class Part extends BaseEntity * * @var float */ - private $averagePrice = 0; + private $averagePrice = 0; /** * The stock level history. @@ -760,8 +760,9 @@ public function getAveragePrice() */ public function setAveragePrice($price) { - if($price != 0) + if ($price != 0) { $this->averagePrice = $price; + } } /** @@ -786,10 +787,11 @@ public function onPreUpdate() public function addStockLevel(StockEntry $stockEntry) { $stockEntry->setPart($this); - - if($this->getAveragePrice() != 0) + + if ($this->getAveragePrice() != 0) { $stockEntry->setPrice($this->getAveragePrice()); - + } + $this->stockLevels->add($stockEntry); } diff --git a/src/PartKeepr/ProjectBundle/Entity/ReportPart.php b/src/PartKeepr/ProjectBundle/Entity/ReportPart.php index fea37675b..874ea9644 100644 --- a/src/PartKeepr/ProjectBundle/Entity/ReportPart.php +++ b/src/PartKeepr/ProjectBundle/Entity/ReportPart.php @@ -42,7 +42,7 @@ class ReportPart extends BaseEntity * @var int */ private $quantity; - + private $remarks; /** @@ -338,13 +338,13 @@ public function setPart($part) return $this; } - + // remark getter public function getRemarks() { return $this->remarks; } - + //remark setter public function setRemarks($remarks) { @@ -352,12 +352,11 @@ public function setRemarks($remarks) return $this; } - public function __toString() { // @todo i18n return sprintf("Used in project report %s %s", $this->getReport()->getName(), - $this->getReport()->getCreateDateTime()->format("Y-m-d H:i:s")) . " / " . parent::__toString(); + $this->getReport()->getCreateDateTime()->format("Y-m-d H:i:s"))." / ".parent::__toString(); } } diff --git a/web/phpinfo.php b/web/phpinfo.php index a4d275df4..18fa22a99 100644 --- a/web/phpinfo.php +++ b/web/phpinfo.php @@ -2,5 +2,3 @@ // Show all information, defaults to INFO_ALL phpinfo(); - -?> From 05fb159616d99bf69a610e27d2b204c4a49b41a8 Mon Sep 17 00:00:00 2001 From: Victor Wollesen Date: Mon, 16 Sep 2019 16:36:37 +0000 Subject: [PATCH 13/13] FILES: Clean up incorrectly committed files. --- app/SymfonyRequirements.php | 805 ------------------------------------ app/check.php | 141 ------- app/config/paramters.php | 271 ------------ web/phpinfo.php | 4 - 4 files changed, 1221 deletions(-) delete mode 100644 app/SymfonyRequirements.php delete mode 100644 app/check.php delete mode 100644 app/config/paramters.php delete mode 100644 web/phpinfo.php diff --git a/app/SymfonyRequirements.php b/app/SymfonyRequirements.php deleted file mode 100644 index 33eb42b97..000000000 --- a/app/SymfonyRequirements.php +++ /dev/null @@ -1,805 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/* - * Users of PHP 5.2 should be able to run the requirements checks. - * This is why the file and all classes must be compatible with PHP 5.2+ - * (e.g. not using namespaces and closures). - * - * ************** CAUTION ************** - * - * DO NOT EDIT THIS FILE as it will be overridden by Composer as part of - * the installation/update process. The original file resides in the - * SensioDistributionBundle. - * - * ************** CAUTION ************** - */ - -/** - * Represents a single PHP requirement, e.g. an installed extension. - * It can be a mandatory requirement or an optional recommendation. - * There is a special subclass, named PhpIniRequirement, to check a php.ini configuration. - * - * @author Tobias Schultze - */ -class Requirement -{ - private $fulfilled; - private $testMessage; - private $helpText; - private $helpHtml; - private $optional; - - /** - * Constructor that initializes the requirement. - * - * @param bool $fulfilled Whether the requirement is fulfilled - * @param string $testMessage The message for testing the requirement - * @param string $helpHtml The help text formatted in HTML for resolving the problem - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement - */ - public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false) - { - $this->fulfilled = (bool) $fulfilled; - $this->testMessage = (string) $testMessage; - $this->helpHtml = (string) $helpHtml; - $this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText; - $this->optional = (bool) $optional; - } - - /** - * Returns whether the requirement is fulfilled. - * - * @return bool true if fulfilled, otherwise false - */ - public function isFulfilled() - { - return $this->fulfilled; - } - - /** - * Returns the message for testing the requirement. - * - * @return string The test message - */ - public function getTestMessage() - { - return $this->testMessage; - } - - /** - * Returns the help text for resolving the problem. - * - * @return string The help text - */ - public function getHelpText() - { - return $this->helpText; - } - - /** - * Returns the help text formatted in HTML. - * - * @return string The HTML help - */ - public function getHelpHtml() - { - return $this->helpHtml; - } - - /** - * Returns whether this is only an optional recommendation and not a mandatory requirement. - * - * @return bool true if optional, false if mandatory - */ - public function isOptional() - { - return $this->optional; - } -} - -/** - * Represents a PHP requirement in form of a php.ini configuration. - * - * @author Tobias Schultze - */ -class PhpIniRequirement extends Requirement -{ - /** - * Constructor that initializes the requirement. - * - * @param string $cfgName The configuration name used for ini_get() - * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, - * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) - * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - * @param bool $optional Whether this is only an optional recommendation not a mandatory requirement - */ - public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false) - { - $cfgValue = ini_get($cfgName); - - if (is_callable($evaluation)) { - if (null === $testMessage || null === $helpHtml) { - throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.'); - } - - $fulfilled = call_user_func($evaluation, $cfgValue); - } else { - if (null === $testMessage) { - $testMessage = sprintf('%s %s be %s in php.ini', - $cfgName, - $optional ? 'should' : 'must', - $evaluation ? 'enabled' : 'disabled' - ); - } - - if (null === $helpHtml) { - $helpHtml = sprintf('Set %s to %s in php.ini*.', - $cfgName, - $evaluation ? 'on' : 'off' - ); - } - - $fulfilled = $evaluation == $cfgValue; - } - - parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional); - } -} - -/** - * A RequirementCollection represents a set of Requirement instances. - * - * @author Tobias Schultze - */ -class RequirementCollection implements IteratorAggregate -{ - /** - * @var Requirement[] - */ - private $requirements = []; - - /** - * Gets the current RequirementCollection as an Iterator. - * - * @return Traversable A Traversable interface - */ - public function getIterator() - { - return new ArrayIterator($this->requirements); - } - - /** - * Adds a Requirement. - * - * @param Requirement $requirement A Requirement instance - */ - public function add(Requirement $requirement) - { - $this->requirements[] = $requirement; - } - - /** - * Adds a mandatory requirement. - * - * @param bool $fulfilled Whether the requirement is fulfilled - * @param string $testMessage The message for testing the requirement - * @param string $helpHtml The help text formatted in HTML for resolving the problem - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - */ - public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null) - { - $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false)); - } - - /** - * Adds an optional recommendation. - * - * @param bool $fulfilled Whether the recommendation is fulfilled - * @param string $testMessage The message for testing the recommendation - * @param string $helpHtml The help text formatted in HTML for resolving the problem - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - */ - public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null) - { - $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true)); - } - - /** - * Adds a mandatory requirement in form of a php.ini configuration. - * - * @param string $cfgName The configuration name used for ini_get() - * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, - * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) - * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - */ - public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) - { - $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false)); - } - - /** - * Adds an optional recommendation in form of a php.ini configuration. - * - * @param string $cfgName The configuration name used for ini_get() - * @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false, - * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement - * @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. - * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. - * Example: You require a config to be true but PHP later removes this config and defaults it to true internally. - * @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived) - * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived) - * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) - */ - public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) - { - $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true)); - } - - /** - * Adds a requirement collection to the current set of requirements. - * - * @param RequirementCollection $collection A RequirementCollection instance - */ - public function addCollection(self $collection) - { - $this->requirements = array_merge($this->requirements, $collection->all()); - } - - /** - * Returns both requirements and recommendations. - * - * @return Requirement[] - */ - public function all() - { - return $this->requirements; - } - - /** - * Returns all mandatory requirements. - * - * @return Requirement[] - */ - public function getRequirements() - { - $array = []; - foreach ($this->requirements as $req) { - if (!$req->isOptional()) { - $array[] = $req; - } - } - - return $array; - } - - /** - * Returns the mandatory requirements that were not met. - * - * @return Requirement[] - */ - public function getFailedRequirements() - { - $array = []; - foreach ($this->requirements as $req) { - if (!$req->isFulfilled() && !$req->isOptional()) { - $array[] = $req; - } - } - - return $array; - } - - /** - * Returns all optional recommendations. - * - * @return Requirement[] - */ - public function getRecommendations() - { - $array = []; - foreach ($this->requirements as $req) { - if ($req->isOptional()) { - $array[] = $req; - } - } - - return $array; - } - - /** - * Returns the recommendations that were not met. - * - * @return Requirement[] - */ - public function getFailedRecommendations() - { - $array = []; - foreach ($this->requirements as $req) { - if (!$req->isFulfilled() && $req->isOptional()) { - $array[] = $req; - } - } - - return $array; - } - - /** - * Returns whether a php.ini configuration is not correct. - * - * @return bool php.ini configuration problem? - */ - public function hasPhpIniConfigIssue() - { - foreach ($this->requirements as $req) { - if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) { - return true; - } - } - - return false; - } - - /** - * Returns the PHP configuration file (php.ini) path. - * - * @return string|false php.ini file path - */ - public function getPhpIniConfigPath() - { - return get_cfg_var('cfg_file_path'); - } -} - -/** - * This class specifies all requirements and optional recommendations that - * are necessary to run the Symfony Standard Edition. - * - * @author Tobias Schultze - * @author Fabien Potencier - */ -class SymfonyRequirements extends RequirementCollection -{ - const LEGACY_REQUIRED_PHP_VERSION = '5.3.3'; - const REQUIRED_PHP_VERSION = '5.5.9'; - - /** - * Constructor that initializes the requirements. - */ - public function __construct() - { - /* mandatory requirements follow */ - - $installedPhpVersion = phpversion(); - $requiredPhpVersion = $this->getPhpRequiredVersion(); - - $this->addRecommendation( - $requiredPhpVersion, - 'Vendors should be installed in order to check all requirements.', - 'Run the composer install command.', - 'Run the "composer install" command.' - ); - - if (false !== $requiredPhpVersion) { - $this->addRequirement( - version_compare($installedPhpVersion, $requiredPhpVersion, '>='), - sprintf('PHP version must be at least %s (%s installed)', $requiredPhpVersion, $installedPhpVersion), - sprintf('You are running PHP version "%s", but Symfony needs at least PHP "%s" to run. - Before using Symfony, upgrade your PHP installation, preferably to the latest version.', - $installedPhpVersion, $requiredPhpVersion), - sprintf('Install PHP %s or newer (installed version is %s)', $requiredPhpVersion, $installedPhpVersion) - ); - } - - $this->addRequirement( - version_compare($installedPhpVersion, '5.3.16', '!='), - 'PHP version must not be 5.3.16 as Symfony won\'t work properly with it', - 'Install PHP 5.3.17 or newer (or downgrade to an earlier PHP version)' - ); - - $this->addRequirement( - is_dir(__DIR__.'/../vendor/composer'), - 'Vendor libraries must be installed', - 'Vendor libraries are missing. Install composer following instructions from http://getcomposer.org/. '. - 'Then run "php composer.phar install" to install them.' - ); - - $cacheDir = is_dir(__DIR__.'/../var/cache') ? __DIR__.'/../var/cache' : __DIR__.'/cache'; - - $this->addRequirement( - is_writable($cacheDir), - 'app/cache/ or var/cache/ directory must be writable', - 'Change the permissions of either "app/cache/" or "var/cache/" directory so that the web server can write into it.' - ); - - $logsDir = is_dir(__DIR__.'/../var/logs') ? __DIR__.'/../var/logs' : __DIR__.'/logs'; - - $this->addRequirement( - is_writable($logsDir), - 'app/logs/ or var/logs/ directory must be writable', - 'Change the permissions of either "app/logs/" or "var/logs/" directory so that the web server can write into it.' - ); - - $this->addPhpIniRequirement( - 'date.timezone', true, false, - 'date.timezone setting must be set', - 'Set the "date.timezone" setting in php.ini* (like Europe/Paris).' - ); - - if (false !== $requiredPhpVersion && version_compare($installedPhpVersion, $requiredPhpVersion, '>=')) { - $timezones = []; - foreach (DateTimeZone::listAbbreviations() as $abbreviations) { - foreach ($abbreviations as $abbreviation) { - $timezones[$abbreviation['timezone_id']] = true; - } - } - - $this->addRequirement( - isset($timezones[@date_default_timezone_get()]), - sprintf('Configured default timezone "%s" must be supported by your installation of PHP', @date_default_timezone_get()), - 'Your default timezone is not supported by PHP. Check for typos in your php.ini file and have a look at the list of deprecated timezones at http://php.net/manual/en/timezones.others.php.' - ); - } - - $this->addRequirement( - function_exists('iconv'), - 'iconv() must be available', - 'Install and enable the iconv extension.' - ); - - $this->addRequirement( - function_exists('json_encode'), - 'json_encode() must be available', - 'Install and enable the JSON extension.' - ); - - $this->addRequirement( - function_exists('session_start'), - 'session_start() must be available', - 'Install and enable the session extension.' - ); - - $this->addRequirement( - function_exists('ctype_alpha'), - 'ctype_alpha() must be available', - 'Install and enable the ctype extension.' - ); - - $this->addRequirement( - function_exists('token_get_all'), - 'token_get_all() must be available', - 'Install and enable the Tokenizer extension.' - ); - - $this->addRequirement( - function_exists('simplexml_import_dom'), - 'simplexml_import_dom() must be available', - 'Install and enable the SimpleXML extension.' - ); - - if (function_exists('apc_store') && ini_get('apc.enabled')) { - if (version_compare($installedPhpVersion, '5.4.0', '>=')) { - $this->addRequirement( - version_compare(phpversion('apc'), '3.1.13', '>='), - 'APC version must be at least 3.1.13 when using PHP 5.4', - 'Upgrade your APC extension (3.1.13+).' - ); - } else { - $this->addRequirement( - version_compare(phpversion('apc'), '3.0.17', '>='), - 'APC version must be at least 3.0.17', - 'Upgrade your APC extension (3.0.17+).' - ); - } - } - - $this->addPhpIniRequirement('detect_unicode', false); - - if (extension_loaded('suhosin')) { - $this->addPhpIniRequirement( - 'suhosin.executor.include.whitelist', - create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'), - false, - 'suhosin.executor.include.whitelist must be configured correctly in php.ini', - 'Add "phar" to suhosin.executor.include.whitelist in php.ini*.' - ); - } - - if (extension_loaded('xdebug')) { - $this->addPhpIniRequirement( - 'xdebug.show_exception_trace', false, true - ); - - $this->addPhpIniRequirement( - 'xdebug.scream', false, true - ); - - $this->addPhpIniRecommendation( - 'xdebug.max_nesting_level', - create_function('$cfgValue', 'return $cfgValue > 100;'), - true, - 'xdebug.max_nesting_level should be above 100 in php.ini', - 'Set "xdebug.max_nesting_level" to e.g. "250" in php.ini* to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.' - ); - } - - $pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null; - - $this->addRequirement( - null !== $pcreVersion, - 'PCRE extension must be available', - 'Install the PCRE extension (version 8.0+).' - ); - - if (extension_loaded('mbstring')) { - $this->addPhpIniRequirement( - 'mbstring.func_overload', - create_function('$cfgValue', 'return (int) $cfgValue === 0;'), - true, - 'string functions should not be overloaded', - 'Set "mbstring.func_overload" to 0 in php.ini* to disable function overloading by the mbstring extension.' - ); - } - - /* optional recommendations follow */ - - if (file_exists(__DIR__.'/../vendor/composer')) { - require_once __DIR__.'/../vendor/autoload.php'; - - try { - $r = new ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle'); - - $contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php'); - } catch (ReflectionException $e) { - $contents = ''; - } - $this->addRecommendation( - file_get_contents(__FILE__) === $contents, - 'Requirements file should be up-to-date', - 'Your requirements file is outdated. Run composer install and re-check your configuration.' - ); - } - - $this->addRecommendation( - version_compare($installedPhpVersion, '5.3.4', '>='), - 'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions', - 'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.' - ); - - $this->addRecommendation( - version_compare($installedPhpVersion, '5.3.8', '>='), - 'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156', - 'Install PHP 5.3.8 or newer if your project uses annotations.' - ); - - $this->addRecommendation( - version_compare($installedPhpVersion, '5.4.0', '!='), - 'You should not use PHP 5.4.0 due to the PHP bug #61453', - 'Your project might not work properly due to the PHP bug #61453 ("Cannot dump definitions which have method calls"). Install PHP 5.4.1 or newer.' - ); - - $this->addRecommendation( - version_compare($installedPhpVersion, '5.4.11', '>='), - 'When using the logout handler from the Symfony Security Component, you should have at least PHP 5.4.11 due to PHP bug #63379 (as a workaround, you can also set invalidate_session to false in the security logout handler configuration)', - 'Install PHP 5.4.11 or newer if your project uses the logout handler from the Symfony Security Component.' - ); - - $this->addRecommendation( - (version_compare($installedPhpVersion, '5.3.18', '>=') && version_compare($installedPhpVersion, '5.4.0', '<')) - || - version_compare($installedPhpVersion, '5.4.8', '>='), - 'You should use PHP 5.3.18+ or PHP 5.4.8+ to always get nice error messages for fatal errors in the development environment due to PHP bug #61767/#60909', - 'Install PHP 5.3.18+ or PHP 5.4.8+ if you want nice error messages for all fatal errors in the development environment.' - ); - - if (null !== $pcreVersion) { - $this->addRecommendation( - $pcreVersion >= 8.0, - sprintf('PCRE extension should be at least version 8.0 (%s installed)', $pcreVersion), - 'PCRE 8.0+ is preconfigured in PHP since 5.3.2 but you are using an outdated version of it. Symfony probably works anyway but it is recommended to upgrade your PCRE extension.' - ); - } - - $this->addRecommendation( - class_exists('DomDocument'), - 'PHP-DOM and PHP-XML modules should be installed', - 'Install and enable the PHP-DOM and the PHP-XML modules.' - ); - - $this->addRecommendation( - function_exists('mb_strlen'), - 'mb_strlen() should be available', - 'Install and enable the mbstring extension.' - ); - - $this->addRecommendation( - function_exists('iconv'), - 'iconv() should be available', - 'Install and enable the iconv extension.' - ); - - $this->addRecommendation( - function_exists('utf8_decode'), - 'utf8_decode() should be available', - 'Install and enable the XML extension.' - ); - - $this->addRecommendation( - function_exists('filter_var'), - 'filter_var() should be available', - 'Install and enable the filter extension.' - ); - - if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $this->addRecommendation( - function_exists('posix_isatty'), - 'posix_isatty() should be available', - 'Install and enable the php_posix extension (used to colorize the CLI output).' - ); - } - - $this->addRecommendation( - extension_loaded('intl'), - 'intl extension should be available', - 'Install and enable the intl extension (used for validators).' - ); - - if (extension_loaded('intl')) { - // in some WAMP server installations, new Collator() returns null - $this->addRecommendation( - null !== new Collator('fr_FR'), - 'intl extension should be correctly configured', - 'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.' - ); - - // check for compatible ICU versions (only done when you have the intl extension) - if (defined('INTL_ICU_VERSION')) { - $version = INTL_ICU_VERSION; - } else { - $reflector = new ReflectionExtension('intl'); - - ob_start(); - $reflector->info(); - $output = strip_tags(ob_get_clean()); - - preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches); - $version = $matches[1]; - } - - $this->addRecommendation( - version_compare($version, '4.0', '>='), - 'intl ICU version should be at least 4+', - 'Upgrade your intl extension with a newer ICU version (4+).' - ); - - $this->addPhpIniRecommendation( - 'intl.error_level', - create_function('$cfgValue', 'return (int) $cfgValue === 0;'), - true, - 'intl.error_level should be 0 in php.ini', - 'Set "intl.error_level" to "0" in php.ini* to inhibit the messages when an error occurs in ICU functions.' - ); - } - - $accelerator = - (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) - || - (extension_loaded('apc') && ini_get('apc.enabled')) - || - (extension_loaded('Zend Optimizer+') && ini_get('zend_optimizerplus.enable')) - || - (extension_loaded('Zend OPcache') && ini_get('opcache.enable')) - || - (extension_loaded('xcache') && ini_get('xcache.cacher')) - || - (extension_loaded('wincache') && ini_get('wincache.ocenabled')); - - $this->addRecommendation( - $accelerator, - 'a PHP accelerator should be installed', - 'Install and/or enable a PHP accelerator (highly recommended).' - ); - - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - $this->addRecommendation( - $this->getRealpathCacheSize() >= 5 * 1024 * 1024, - 'realpath_cache_size should be at least 5M in php.ini', - 'Setting "realpath_cache_size" to e.g. "5242880" or "5M" in php.ini* may improve performance on Windows significantly in some cases.' - ); - } - - $this->addPhpIniRecommendation('short_open_tag', false); - - $this->addPhpIniRecommendation('magic_quotes_gpc', false, true); - - $this->addPhpIniRecommendation('register_globals', false, true); - - $this->addPhpIniRecommendation('session.auto_start', false); - - $this->addRecommendation( - class_exists('PDO'), - 'PDO should be installed', - 'Install PDO (mandatory for Doctrine).' - ); - - if (class_exists('PDO')) { - $drivers = PDO::getAvailableDrivers(); - $this->addRecommendation( - count($drivers) > 0, - sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'), - 'Install PDO drivers (mandatory for Doctrine).' - ); - } - } - - /** - * Loads realpath_cache_size from php.ini and converts it to int. - * - * (e.g. 16k is converted to 16384 int) - * - * @return int - */ - protected function getRealpathCacheSize() - { - $size = ini_get('realpath_cache_size'); - $size = trim($size); - $unit = ''; - if (!ctype_digit($size)) { - $unit = strtolower(substr($size, -1, 1)); - $size = (int) substr($size, 0, -1); - } - switch ($unit) { - case 'g': - return $size * 1024 * 1024 * 1024; - case 'm': - return $size * 1024 * 1024; - case 'k': - return $size * 1024; - default: - return (int) $size; - } - } - - /** - * Defines PHP required version from Symfony version. - * - * @return string|false The PHP required version or false if it could not be guessed - */ - protected function getPhpRequiredVersion() - { - if (!file_exists($path = __DIR__.'/../composer.lock')) { - return false; - } - - $composerLock = json_decode(file_get_contents($path), true); - foreach ($composerLock['packages'] as $package) { - $name = $package['name']; - if ('symfony/symfony' !== $name && 'symfony/http-kernel' !== $name) { - continue; - } - - return (int) $package['version'][1] > 2 ? self::REQUIRED_PHP_VERSION : self::LEGACY_REQUIRED_PHP_VERSION; - } - - return false; - } -} diff --git a/app/check.php b/app/check.php deleted file mode 100644 index 234d32712..000000000 --- a/app/check.php +++ /dev/null @@ -1,141 +0,0 @@ -getPhpIniConfigPath(); - -echo_title('Symfony Requirements Checker'); - -echo '> PHP is using the following php.ini file:'.PHP_EOL; -if ($iniPath) { - echo_style('green', ' '.$iniPath); -} else { - echo_style('yellow', ' WARNING: No configuration file (php.ini) used by PHP!'); -} - -echo PHP_EOL.PHP_EOL; - -echo '> Checking Symfony requirements:'.PHP_EOL.' '; - -$messages = []; -foreach ($symfonyRequirements->getRequirements() as $req) { - if ($helpText = get_error_message($req, $lineSize)) { - echo_style('red', 'E'); - $messages['error'][] = $helpText; - } else { - echo_style('green', '.'); - } -} - -$checkPassed = empty($messages['error']); - -foreach ($symfonyRequirements->getRecommendations() as $req) { - if ($helpText = get_error_message($req, $lineSize)) { - echo_style('yellow', 'W'); - $messages['warning'][] = $helpText; - } else { - echo_style('green', '.'); - } -} - -if ($checkPassed) { - echo_block('success', 'OK', 'Your system is ready to run Symfony projects'); -} else { - echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects'); - - echo_title('Fix the following mandatory requirements', 'red'); - - foreach ($messages['error'] as $helpText) { - echo ' * '.$helpText.PHP_EOL; - } -} - -if (!empty($messages['warning'])) { - echo_title('Optional recommendations to improve your setup', 'yellow'); - - foreach ($messages['warning'] as $helpText) { - echo ' * '.$helpText.PHP_EOL; - } -} - -echo PHP_EOL; -echo_style('title', 'Note'); -echo ' The command console could use a different php.ini file'.PHP_EOL; -echo_style('title', '~~~~'); -echo ' than the one used with your web server. To be on the'.PHP_EOL; -echo ' safe side, please check the requirements from your web'.PHP_EOL; -echo ' server using the '; -echo_style('yellow', 'web/config.php'); -echo ' script.'.PHP_EOL; -echo PHP_EOL; - -exit($checkPassed ? 0 : 1); - -function get_error_message(Requirement $requirement, $lineSize) -{ - if ($requirement->isFulfilled()) { - return; - } - - $errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL; - $errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL; - - return $errorMessage; -} - -function echo_title($title, $style = null) -{ - $style = $style ?: 'title'; - - echo PHP_EOL; - echo_style($style, $title.PHP_EOL); - echo_style($style, str_repeat('~', strlen($title)).PHP_EOL); - echo PHP_EOL; -} - -function echo_style($style, $message) -{ - // ANSI color codes - $styles = [ - 'reset' => "\033[0m", - 'red' => "\033[31m", - 'green' => "\033[32m", - 'yellow' => "\033[33m", - 'error' => "\033[37;41m", - 'success' => "\033[37;42m", - 'title' => "\033[34m", - ]; - $supports = has_color_support(); - - echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : ''); -} - -function echo_block($style, $title, $message) -{ - $message = ' '.trim($message).' '; - $width = strlen($message); - - echo PHP_EOL.PHP_EOL; - - echo_style($style, str_repeat(' ', $width).PHP_EOL); - echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT).PHP_EOL); - echo_style($style, str_pad($message, $width, ' ', STR_PAD_RIGHT).PHP_EOL); - echo_style($style, str_repeat(' ', $width).PHP_EOL); -} - -function has_color_support() -{ - static $support; - - if (null === $support) { - if (DIRECTORY_SEPARATOR == '\\') { - $support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'); - } else { - $support = function_exists('posix_isatty') && @posix_isatty(STDOUT); - } - } - - return $support; -} diff --git a/app/config/paramters.php b/app/config/paramters.php deleted file mode 100644 index 0c1d9d7dd..000000000 --- a/app/config/paramters.php +++ /dev/null @@ -1,271 +0,0 @@ -setParameter('database_driver', 'pdo_mysql'); - -/** - * Specifies the hostname for the database. - */ -$container->setParameter('database_host', 'localhost'); -/** - * Specifies the database port. - */ -$container->setParameter('database_port', '3306'); - -/** - * Specifies the database name. - */ -$container->setParameter('database_name', 'symfony'); - -/** - * Specifies the username for the database. - */ -$container->setParameter('database_user', 'root'); - -/** - * Specifies the password for the database. - */ -$container->setParameter('database_password', null); - -//====================================================================================================================== -// Mailer Settings -// Currently not used, the defaults are fine -//====================================================================================================================== - -// The mailer transport. Can be smtp, mail, sendmail or gmail -$container->setParameter('mailer_transport', null); - -// The mail server host name or IP -$container->setParameter('mailer_host', null); - -// The mail server port to use -$container->setParameter('mailer_port', null); - -// The encryption method to use. Can be ssl, tls or null for unencrypted mail transport -$container->setParameter('mailer_encryption', null); - -// The mail server username -$container->setParameter('mailer_user', null); - -// The mail server password -$container->setParameter('mailer_password', null); - -// The mail server auth mode. Can be plain, login or cram-md5 -$container->setParameter('mailer_auth_mode', null); - -//====================================================================================================================== -// Misc framework settings -//====================================================================================================================== - -// The locale to use. Currently only en is supported -$container->setParameter('locale', 'en'); - -// The secret. See http://symfony.com/doc/current/reference/configuration/framework.html#secret -$container->setParameter('secret', 'COAAFJGGLPHPDGGNCNILHFGECFMMACKC'); - -//====================================================================================================================== -// LDAP Configuration -// Example for Active Directory: -// https://github.com/Maks3w/FR3DLdapBundle/blob/master/Resources/doc/cookbook/active-directory.md -//====================================================================================================================== - -// The LDAP Server Host -$container->setParameter('fr3d_ldap.driver.host', '127.0.0.1'); - -// The LDAP Sever Port -$container->setParameter('fr3d_ldap.driver.port', null); - -// The username to use for LDAP queries -$container->setParameter('fr3d_ldap.driver.username', null); - -// The password to use for LDAP queries -$container->setParameter('fr3d_ldap.driver.password', null); - -// true to require a DN for binding attemts, false otherwise -$container->setParameter('fr3d_ldap.driver.bindRequiresDn', false); - -// The base DN to query for users -$container->setParameter('fr3d_ldap.driver.baseDn', ''); - -// sprintf format %s will be the username -$container->setParameter('fr3d_ldap.driver.accountFilterFormat', null); - -$container->setParameter('fr3d_ldap.driver.optReferrals', null); - -// true to use SSL, false otherwise -$container->setParameter('fr3d_ldap.driver.useSsl', null); - -// true to use startTls, false otherwise -$container->setParameter('fr3d_ldap.driver.useStartTls', null); - -// currently not used -$container->setParameter('fr3d_ldap.driver.accountCanonicalForm', null); - -$container->setParameter('fr3d_ldap.driver.accountDomainName', null); -$container->setParameter('fr3d_ldap.driver.accountDomainNameShort', null); - -// set to true to enable LDAP -$container->setParameter('fr3d_ldap.user.enabled', false); - -// sets the base DN -$container->setParameter('fr3d_ldap.user.baseDn', 'dc=blabla,dc=com'); - -// The filter to use for queries -$container->setParameter('fr3d_ldap.user.filter', null); - -// The username attribute -$container->setParameter('fr3d_ldap.user.attribute.username', "samaccountname"); - -// The email attribute -$container->setParameter('fr3d_ldap.user.attribute.email', "email"); - -//====================================================================================================================== -// PartKeepr settings -//====================================================================================================================== - -// The authentication provider to use. Can be either PartKeepr.Auth.WSSEAuthenticationProvider or -// PartKeepr.Auth.HTTPBasicAuthenticationProvider -$container->setParameter('authentication_provider', 'PartKeepr.Auth.WSSEAuthenticationProvider'); - -/** - * Specifies if the frontend should perform an auto-login. - */ -$container->setParameter('partkeepr.frontend.auto_login.enabled', false); - -/** - * Specifies the auto-login username. - */ -$container->setParameter('partkeepr.frontend.auto_login.username', 'admin'); - -/** - * Specifies the auto-login password. - */ -$container->setParameter('partkeepr.frontend.auto_login.password', 'admin'); - -/** - * Specifies the base_url for the PartKeepr frontend. - * Usually this is not required, but if you run PartKeepr behind a reverse - * proxy with a different path, you can set it here. - * - * Please note that you need to create an additional file, see - * https://wiki.partkeepr.org/wiki/KB00008:PartKeepr_behind_a_reverse_proxy - * - * Example: If PartKeepr runs on / within a docker container and your reverse - * proxy maps it on https://www.example.org/parts, you can set the - * base_url to https://www.example.org/parts - */ -$container->setParameter('partkeepr.frontend.base_url', false); - -/** - * Specifies the category path separator. - */ -$container->setParameter('partkeepr.category.path_separator', ' ➤ '); - -/** - * Specifies a message of the day. Set to any string instead of false - * to display a MOTD. Example - * $container->setParameter('partkeepr.frontend.motd', "This is a MOTD");. - */ -$container->setParameter('partkeepr.frontend.motd', false); - -/** - * Specifies if a quota should be used. - * If set to false, no quota is used. Set it to a numeric value to set a quota in bytes. - */ -$container->setParameter('partkeepr.filesystem.quota', false); - -/** - * Specifies the dunglas cache. Defaults to false. - * You can use the APCu cache by specifying "api.mapping.cache.apc" here. - * - * Further reading: https://api-platform.com/doc/1.0/api-bundle/performances - */ -$container->setParameter('cache.dunglas', false); - -/** - * Specifies the doctrine cache. Defaults to "array", but can be "apc". - * - * Further reading: http://symfony.com/doc/current/bundles/DoctrineBundle/configuration.html#caching-drivers - * - * For complex caching scenarios, you are advised to use a custom configuration file as described at the top of this - * file. - */ -$container->setParameter('cache.doctrine', 'array'); - -/** - * Defines if a maintenance page should be displayed. - */ -$container->setParameter('partkeepr.maintenance', false); - -/** - * Defines if a maintenance page should be displayed. Set to false to prevent a maintenance page being - * displayed, or to a string which should occur on the maintenance page. - */ -$container->setParameter('partkeepr.maintenance.title', ''); - -/** - * Defines if a maintenance page should be displayed. Set to false to prevent a maintenance page being - * displayed, or to a string which should occur on the maintenance page. - */ -$container->setParameter('partkeepr.maintenance.message', ''); - -/** - * Defines a limit for the maximum amount of users allowed. Valid values are false (no limit) or an integer number. - */ -$container->setParameter('partkeepr.users.limit', false); - -/** - * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number. - */ -$container->setParameter('partkeepr.parts.limit', false); - -/** - * Defines if the internal part number must be unique or not. Note that empty internal part numbers aren't checked - - * if you require to enforce an internal part number, also set the field internalPartNumber to mandatory. - * - * Defaults to false - */ -$container->setParameter('partkeepr.parts.internalpartnumberunique', false); - -/** - * Defines a limit for the maximum amount of parts allowed. Valid values are false (no limit) or an integer number. - */ -$container->setParameter('partkeepr.upload.limit', false); - -/** - * Specifies the PartKeepr data directory. - */ -$container->setParameter('partkeepr.filesystem.data_directory', '%kernel.root_dir%/../data/'); - -/** - * Specifies if PartKeepr should check for non-running cronjobs. - */ -$container->setParameter('partkeepr.cronjob.check', true); - -/** - * Specifies which API key PartKeepr should use to talk to OctoPart. You can get an API key by registering at - * https://octopart.com/api/home and then registering an application. - */ -$container->setParameter('partkeepr.octopart.apikey', ''); - -/** - * Specifies which URL contains the patreon status. If you do not wish to display the patreon status, - * set this parameter to false. Please note that we rely on your Patreon pledges to ensure further - * development of PartKeepr. - */ -$container->setParameter('partkeepr.patreon.statusuri', 'https://www.partkeepr.org/patreon.json'); diff --git a/web/phpinfo.php b/web/phpinfo.php deleted file mode 100644 index 18fa22a99..000000000 --- a/web/phpinfo.php +++ /dev/null @@ -1,4 +0,0 @@ -