Commit 4445a198031c612601fd0432a16bdcf9ee4d577a

Authored by Alexey Boroda
2 parents b6fdfe93 543b9b1c

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	composer.json
.gitignore
... ... @@ -34,4 +34,4 @@ phpunit.phar
34 34 # vagrant runtime
35 35 /.vagrant
36 36 /artweb/
37 37 -/storage
  38 +/storage
38 39 \ No newline at end of file
... ...
Initializer.php 0 → 100644
  1 +<?php
  2 +
  3 + /**
  4 + * Class Initializer
  5 + *
  6 + * Class to initialize Artbox application
  7 + */
  8 + class Initializer
  9 + {
  10 + private $params = [];
  11 + private $root;
  12 + private $envs = [];
  13 + private $environment;
  14 + private $db = [];
  15 + private static $instance;
  16 +
  17 + const VERSION = '1.0';
  18 + const CALLBACKS = [
  19 + 'setCookieValidationKey',
  20 + 'setWritable',
  21 + 'setExecutable',
  22 + 'createSymlink',
  23 + ];
  24 +
  25 + /**
  26 + * Initialize application
  27 + */
  28 + public static function initialize()
  29 + {
  30 + $instance = self::getInstance();
  31 + $instance->defineEnvironment();
  32 + $instance->startInitialization();
  33 + if ($instance->askInitDb()) {
  34 + do {
  35 + $instance->defineDb();
  36 + } while (!$instance->databaseCheck());
  37 + $instance->migrate();
  38 + $instance->createUser();
  39 + $instance->congratulate();
  40 + }
  41 + }
  42 +
  43 + /**
  44 + * Get instance of Initializer
  45 + *
  46 + * @return mixed
  47 + */
  48 + public static function getInstance(): Initializer
  49 + {
  50 + if (empty( self::$instance )) {
  51 + self::$instance = new self();
  52 + }
  53 + return self::$instance;
  54 + }
  55 +
  56 + /**
  57 + * Initializer private constructor. You can get Singleton with getInstance()
  58 + *
  59 + * Availiable options:
  60 + * * --env - One of available environments
  61 + * * --overwrite - Do overwrite all files without confirmation
  62 + * * --dbinit - Initialize database after app initialization
  63 + * * --dbtype - Database type. Available: postgresql, mysql
  64 + * * --host - Database host, default to 127.0.0.1
  65 + * * --port - Database port used by postgresql, default to 5432
  66 + * * --schema - Database schema for postresql, default to public
  67 + * * --dbname - Database name, required
  68 + * * --username - Database username, required
  69 + * * --password - Database password, required
  70 + * * --migrationPath - Migration path, default to vendor/artweb/artbox-core/migrations
  71 + * * --migrate - Whether to migrate, default to apply, set no to skip migration
  72 + * * --user_username - Username for user creation
  73 + * * --user_email - Email for user creation
  74 + * * --user_password - Password for user creation
  75 + * * --user - Whether to create user, default to yes, set no to skip creation
  76 + * * --defaultuser - Whether to use default user creation
  77 + * * --o - Webpage to open after intallaction process
  78 + * * --fun - Run HOLLYWOOD BABY!!!
  79 + *
  80 + * @see Initializer::getInstance()
  81 + */
  82 + private function __construct()
  83 + {
  84 + echo $this->formatMessage(
  85 + "\tArtbox Application Initialization Tool v" . self::VERSION,
  86 + [ 'bold' ]
  87 + ) . "\n\n";
  88 + }
  89 +
  90 + /**
  91 + * Define environment for an application
  92 + *
  93 + * @return string
  94 + */
  95 + private function defineEnvironment()
  96 + {
  97 + $envName = $this->getParamValue('env');
  98 + $envs = $this->getEnvironmentNames();
  99 + if (empty( $envName ) || $envName === '1') {
  100 + do {
  101 + $envName = $this->askEnvironment($envs);
  102 + echo "\n Initialize the application under '{$envName}' environment? [yes|no] ";
  103 + $answer = trim(fgets(STDIN));
  104 + } while (strncasecmp($answer, 'y', 1));
  105 + } else {
  106 + if (!in_array($envName, $envs)) {
  107 + $this->printError("Wrong environment name, available list: " . implode(', ', $envs));
  108 + exit( 1 );
  109 + }
  110 + }
  111 + $this->environment = $this->envs[ $envName ];
  112 + return $this->environment;
  113 + }
  114 +
  115 + /**
  116 + * Start actual application initialization with files overwriting
  117 + */
  118 + private function startInitialization()
  119 + {
  120 + echo "\n Start initialization\n";
  121 + echo " =====================\n";
  122 +
  123 + $this->rewriteFiles();
  124 + $this->callback();
  125 + echo "\n App initialization completed\n";
  126 + echo " ==============================\n";
  127 + }
  128 +
  129 + /**
  130 + * Ask whether to init databse. If dbinit param is set, this step will be skipped.
  131 + *
  132 + * @return bool
  133 + */
  134 + private function askInitDb(): bool
  135 + {
  136 + echo " Start database initialization\n";
  137 + $params = $this->getParams();
  138 + if (!isset( $params[ 'dbinit' ] )) {
  139 + do {
  140 + echo $this->formatMessage("\n Init the database? [yes|no] ", [ 'bold' ]);
  141 + $answer = trim(fgets(STDIN));
  142 + } while (( strncasecmp($answer, 'y', 1) !== 0 ) && ( strncasecmp($answer, 'n', 1) !== 0 ));
  143 + if (strncasecmp($answer, 'n', 1) == 0) {
  144 + $this->noDatabaseMessage();
  145 + }
  146 + }
  147 + return true;
  148 + }
  149 +
  150 + /**
  151 + * Define which database driver to use. Available options: postgresql, mysql
  152 + */
  153 + private function defineDb()
  154 + {
  155 + $params = $this->getParams();
  156 + if (isset( $params[ 'dbinit' ] )) {
  157 + $this->validateConnection();
  158 + } else {
  159 + $answer = '';
  160 + do {
  161 + if (!empty( $answer )) {
  162 + $this->printError("Incorrect database type. Try again or write 'quit' to exit");
  163 + }
  164 + echo "\n Which database do you want to use? [postgresql|mysql] ";
  165 + $answer = trim(fgets(STDIN));
  166 +
  167 + } while (( strncasecmp($answer, 'q', 1) !== 0 ) && ( !in_array(
  168 + $answer,
  169 + [
  170 + 'postgresql',
  171 + 'mysql',
  172 + 'p',
  173 + 'm',
  174 + ]
  175 + ) ));
  176 + if (strncasecmp($answer, 'q', 1) === 0) {
  177 + $this->noDatabaseMessage();
  178 + }
  179 + if (strncasecmp($answer, 'p', 1) === 0) {
  180 + $answer = 'postgresql';
  181 + } else {
  182 + $answer = 'mysql';
  183 + }
  184 + if ($answer == 'postgresql') {
  185 + $this->initPostgres();
  186 + } else {
  187 + $this->initMysql();
  188 + }
  189 + }
  190 + $this->initDb();
  191 + }
  192 +
  193 + /**
  194 + * Get parsed params
  195 + *
  196 + * @see Initializer::parseParams()
  197 + *
  198 + * @return array
  199 + */
  200 + private function getParams(): array
  201 + {
  202 + if (empty( $this->params )) {
  203 + $this->parseParams();
  204 + }
  205 + return $this->params;
  206 + }
  207 +
  208 + /**
  209 + * Get params from input string
  210 + * For example
  211 + *
  212 + * **<code>php init test --param1=value1 --param2=value2</code>**
  213 + *
  214 + * will get
  215 + *
  216 + * <code>**
  217 + * [
  218 + * test,
  219 + * value1,
  220 + * value2
  221 + * ]
  222 + * </code>
  223 + *
  224 + * @return array
  225 + */
  226 + private function parseParams(): array
  227 + {
  228 + $rawParams = [];
  229 + if (isset( $_SERVER[ 'argv' ] )) {
  230 + $rawParams = $_SERVER[ 'argv' ];
  231 + array_shift($rawParams);
  232 + }
  233 +
  234 + $params = [];
  235 + foreach ($rawParams as $param) {
  236 + if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
  237 + $name = $matches[ 1 ];
  238 + $params[ $name ] = isset( $matches[ 3 ] ) ? $matches[ 3 ] : true;
  239 + } else {
  240 + $params[] = $param;
  241 + }
  242 + }
  243 + $this->params = $params;
  244 + return $this->params;
  245 + }
  246 +
  247 + /**
  248 + * Get value of input param. Empty string if not exist.
  249 + *
  250 + * @param string $name
  251 + *
  252 + * @return string
  253 + */
  254 + private function getParamValue(string $name): string
  255 + {
  256 + $params = $this->getParams();
  257 + if (isset( $params[ $name ] ) && !empty( $params[ $name ] )) {
  258 + return $params[ $name ];
  259 + } else {
  260 + return '';
  261 + }
  262 + }
  263 +
  264 + /**
  265 + * Get project root directory according to file system
  266 + *
  267 + * @return mixed
  268 + */
  269 + private function getRoot(): string
  270 + {
  271 + if (empty( $this->root )) {
  272 + $this->root = str_replace('\\', '/', __DIR__);
  273 + }
  274 + return $this->root;
  275 + }
  276 +
  277 + /**
  278 + * Get available environments from environments/index.php file
  279 + *
  280 + * Follow environments/index.php manifest to create your own environments
  281 + *
  282 + * @return array
  283 + */
  284 + private function getEnvironments(): array
  285 + {
  286 + $path = "{$this->getRoot()}/environments/index.php";
  287 + if (empty( $this->envs )) {
  288 + /** @noinspection PhpIncludeInspection */
  289 + $this->envs = require( $path );
  290 + }
  291 + if (empty( $this->envs )) {
  292 + die( "There are no available environments in $path" );
  293 + }
  294 + return $this->envs;
  295 + }
  296 +
  297 + /**
  298 + * Get environment names
  299 + *
  300 + * @return array
  301 + */
  302 + private function getEnvironmentNames(): array
  303 + {
  304 + return array_keys($this->getEnvironments());
  305 + }
  306 +
  307 + /**
  308 + * Show user variants to choose environment from
  309 + *
  310 + * @param array $envs
  311 + *
  312 + * @return string
  313 + */
  314 + private function askEnvironment(array $envs): string
  315 + {
  316 + echo "Which environment do you want the application to be initialized in?\n\n";
  317 + foreach ($envs as $i => $name) {
  318 + echo " [$i] $name\n";
  319 + }
  320 + $answer = $this->offerEnvironment(count($envs));
  321 + while (!( ( ctype_digit($answer) && in_array($answer, range(0, count($envs) - 1)) ) || $answer === 'q' )) {
  322 + $answer = $this->offerEnvironment(count($envs));
  323 + }
  324 + if ($answer === 'q') {
  325 + echo "\n Quit initialization.\n";
  326 + exit( 0 );
  327 + } else {
  328 + if (isset( $envs[ $answer ] )) {
  329 + $envName = $envs[ $answer ];
  330 + } else {
  331 + die( "Error while trying to get environment name. Try another one." );
  332 + }
  333 + }
  334 + return $envName;
  335 + }
  336 +
  337 + /**
  338 + * Offer user to choose environment number
  339 + *
  340 + * @param int $count
  341 + *
  342 + * @return string
  343 + */
  344 + private function offerEnvironment(int $count): string
  345 + {
  346 + echo "\n Your choice [0-" . ( $count - 1 ) . ', or "q" to quit] ';
  347 + return trim(fgets(STDIN));
  348 + }
  349 +
  350 + /**
  351 + * Rewrite files by files in <code>environments/$environment['path']</code>
  352 + */
  353 + private function rewriteFiles()
  354 + {
  355 + $environment = $this->environment;
  356 + $root = $this->getRoot();
  357 + if (isset( $environment[ 'path' ] ) && !empty( $environment[ 'path' ] )) {
  358 + $path = $environment[ 'path' ];
  359 + } else {
  360 + $this->printError('Environment configuration failed. Please set path value.');
  361 + exit( 1 );
  362 + }
  363 + $files = $this->getFileList("$root/environments/$path");
  364 + if (isset( $environment[ 'skipFiles' ] )) {
  365 + $skipFiles = $environment[ 'skipFiles' ];
  366 + array_walk(
  367 + $skipFiles,
  368 + function (&$value) use ($root) {
  369 + $value = "$root/$value";
  370 + }
  371 + );
  372 + $files = array_diff(
  373 + $files,
  374 + array_intersect_key(
  375 + $environment[ 'skipFiles' ],
  376 + array_filter($skipFiles, 'file_exists')
  377 + )
  378 + );
  379 + }
  380 + $all = false;
  381 + foreach ($files as $file) {
  382 + if (!$this->copyFile("environments/{$path}/$file", $file, $all)) {
  383 + break;
  384 + }
  385 + }
  386 + }
  387 +
  388 + /**
  389 + * Recursively get all files from $root directory.
  390 + *
  391 + * This will ignore .git, .svn directories.
  392 + *
  393 + * @param string $root
  394 + * @param string $basePath
  395 + *
  396 + * @return array
  397 + */
  398 + private function getFileList(string $root, string $basePath = ''): array
  399 + {
  400 + $files = [];
  401 + $handle = opendir($root);
  402 + while (( $path = readdir($handle) ) !== false) {
  403 + if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
  404 + continue;
  405 + }
  406 + $fullPath = "$root/$path";
  407 + $relativePath = $basePath === '' ? $path : "$basePath/$path";
  408 + if (is_dir($fullPath)) {
  409 + $files = array_merge($files, $this->getFileList($fullPath, $relativePath));
  410 + } else {
  411 + $files[] = $relativePath;
  412 + }
  413 + }
  414 + closedir($handle);
  415 + return $files;
  416 + }
  417 +
  418 + /**
  419 + * Run callbacks for application initialization
  420 + */
  421 + private function callback()
  422 + {
  423 + $environment = $this->environment;
  424 + foreach (self::CALLBACKS as $callback) {
  425 + if (!empty( $environment[ $callback ] )) {
  426 + $this->$callback($environment[ $callback ]);
  427 + }
  428 + }
  429 + }
  430 +
  431 + /**
  432 + * Set directories in $environment['setWrotable'] to chmod 0777
  433 + *
  434 + * @param $paths
  435 + */
  436 + private function setWritable(array $paths)
  437 + {
  438 + $root = $this->getRoot();
  439 + foreach ($paths as $writable) {
  440 + $fullPath = "$root/$writable";
  441 + if (is_dir($fullPath)) {
  442 + if (@chmod($fullPath, 0777)) {
  443 + echo $this->formatMessage(
  444 + " ***** Set writable $writable (chmod 0777)",
  445 + [ 'fg-yellow' ]
  446 + ) . "\n";
  447 + } else {
  448 + $this->printError("Operation chmod not permitted for directory $writable.");
  449 + }
  450 + } else {
  451 + if (!@mkdir($fullPath, 0777, true)) {
  452 + $this->printError("Directory $writable does not exist and cannot be created.");
  453 + }
  454 + }
  455 + }
  456 + }
  457 +
  458 + /**
  459 + * Set files in $environment['setExecutable'] to chmod 0755
  460 + *
  461 + * @param $paths
  462 + */
  463 + private function setExecutable(array $paths)
  464 + {
  465 + $root = $this->getRoot();
  466 + foreach ($paths as $executable) {
  467 + $fullPath = "$root/$executable";
  468 + if (file_exists($fullPath)) {
  469 + if (@chmod($fullPath, 0755)) {
  470 + echo $this->formatMessage(" ***** Set executable $executable (chmod 0755)") . "\n";
  471 + } else {
  472 + $this->printError("Operation chmod not permitted for $executable.");
  473 + }
  474 + } else {
  475 + $this->printError("$executable does not exist.");
  476 + }
  477 + }
  478 + }
  479 +
  480 + /**
  481 + * Set cookie validation keys to files in $environment['setCookieValidationKey'].
  482 + *
  483 + * @param $paths
  484 + */
  485 + private function setCookieValidationKey(array $paths)
  486 + {
  487 + $root = $this->getRoot();
  488 + foreach ($paths as $file) {
  489 + echo $this->formatMessage(
  490 + " ***** Generate cookie validation key in $file",
  491 + [
  492 + 'bold',
  493 + 'fg-magenta',
  494 + ]
  495 + ) . "\n";
  496 + $file = $root . '/' . $file;
  497 + $length = 32;
  498 + $bytes = openssl_random_pseudo_bytes($length);
  499 + $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
  500 + $this->setParam('cookieValidationKey', $key, $file);
  501 + }
  502 + }
  503 +
  504 + private function createSymlink(array $links)
  505 + {
  506 + $root = $this->getRoot();
  507 + foreach ($links as $link => $target) {
  508 + //first removing folders to avoid errors if the folder already exists
  509 + @rmdir($root . "/" . $link);
  510 + //next removing existing symlink in order to update the target
  511 + if (is_link($root . "/" . $link)) {
  512 + @unlink($root . "/" . $link);
  513 + }
  514 + if (@symlink($root . "/" . $target, $root . "/" . $link)) {
  515 + echo $this->formatMessage(" ***** Symlink $root/$target $root/$link", [ 'fg-blue' ]) . "\n";
  516 + } else {
  517 + $this->printError("Cannot create symlink $root/$target $root/$link.");
  518 + }
  519 + }
  520 + }
  521 +
  522 + /**
  523 + * Copy file from environment directory to project directory
  524 + *
  525 + * @param string $source Environment source file path
  526 + * @param string $target Project file path target
  527 + * @param bool $all Rewrite all flag
  528 + *
  529 + * @return bool
  530 + */
  531 + private function copyFile(string $source, string $target, bool &$all)
  532 + {
  533 + $root = $this->getRoot();
  534 + $params = $this->getParams();
  535 + if (!is_file($root . '/' . $source)) {
  536 + echo $this->formatMessage(" ----- skip $target ($source not exist)", [ 'fg-cyan' ]) . "\n";
  537 + return true;
  538 + }
  539 + if (is_file($root . '/' . $target)) {
  540 + if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
  541 + echo $this->formatMessage(" ----- unchanged $target", [ 'fg-cyan' ]) . "\n";
  542 + return true;
  543 + }
  544 + if ($all) {
  545 + echo $this->formatMessage(" ----- overwrite $target", [ 'fg-blue' ]) . "\n";
  546 + } else {
  547 + echo $this->formatMessage(" -- exist $target", [ 'fg-magenta' ]) . "\n";
  548 + echo " overwrite? [Yes|No|All|Quit] ";
  549 +
  550 + $answer = !empty( $params[ 'overwrite' ] ) ? $params[ 'overwrite' ] : trim(fgets(STDIN));
  551 + echo "\n";
  552 + if (!strncasecmp($answer, 'q', 1)) {
  553 + return false;
  554 + } else {
  555 + if (!strncasecmp($answer, 'y', 1)) {
  556 + echo $this->formatMessage(" ----- overwrite $target", [ 'fg-blue' ]) . "\n";
  557 + } else {
  558 + if (!strncasecmp($answer, 'a', 1)) {
  559 + echo $this->formatMessage(" ----- overwrite $target", [ 'fg-blue' ]) . "\n";
  560 + $all = true;
  561 + } else {
  562 + echo $this->formatMessage(
  563 + " ----- skip $target ($source not exist)",
  564 + [ 'fg-cyan' ]
  565 + ) . "\n";
  566 + return true;
  567 + }
  568 + }
  569 + }
  570 + }
  571 + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
  572 + return true;
  573 + }
  574 + echo "\n" . $this->formatMessage(" ----- generate $target", [ 'fg-green' ]) . "\n";
  575 + @mkdir(dirname($root . '/' . $target), 0777, true);
  576 + file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
  577 + return true;
  578 + }
  579 +
  580 + /**
  581 + * Set param in file to particular value.
  582 + *
  583 + * For example: setParam('param', 'value', 'config.php') will replace content in config.php
  584 + *
  585 + * from
  586 + *
  587 + * 'param' => ''
  588 + *
  589 + * to
  590 + *
  591 + * 'param' => 'value'
  592 + *
  593 + * @param string $param
  594 + * @param string $value
  595 + * @param string $file
  596 + * @param bool $noQuote
  597 + * @param bool $force
  598 + * @param bool $alternate
  599 + */
  600 + private function setParam(
  601 + string $param,
  602 + string $value,
  603 + string $file,
  604 + bool $noQuote = false,
  605 + bool $force = false,
  606 + bool $alternate = false
  607 + ) {
  608 + if ($alternate) {
  609 + $regexp = '/(("|\')db("|\')\s*=>\s*)(.*|.*)/';
  610 + } else {
  611 + if ($force) {
  612 + $regexp = '/(("|\')' . $param . '("|\')\s*=>\s*)(".*"|\'.*\')/';
  613 + } else {
  614 + $regexp = '/(("|\')' . $param . '("|\')\s*=>\s*)(""|\'\')/';
  615 + }
  616 + }
  617 + if ($noQuote) {
  618 + $content = preg_replace(
  619 + $regexp,
  620 + "\\1$value",
  621 + file_get_contents($file)
  622 + );
  623 + } else {
  624 + $content = preg_replace(
  625 + $regexp,
  626 + "\\1'$value'",
  627 + file_get_contents($file)
  628 + );
  629 + }
  630 + file_put_contents($file, $content);
  631 + }
  632 +
  633 + /**
  634 + * Init postgres connection
  635 + *
  636 + * @return array
  637 + */
  638 + private function initPostgres(): array
  639 + {
  640 + $db = [
  641 + 'dbtype' => 'postgresql',
  642 + ];
  643 + echo "\n Enter your database host: ";
  644 + $host = trim(fgets(STDIN));
  645 + echo "\n Enter your database port: ";
  646 + $port = trim(fgets(STDIN));
  647 + echo "\n Enter your database schema: ";
  648 + $db[ 'schema' ] = trim(fgets(STDIN));
  649 + echo "\n Enter your database name: ";
  650 + $name = trim(fgets(STDIN));
  651 + echo "\n Enter your database username: ";
  652 + $db[ 'username' ] = trim(fgets(STDIN));
  653 + echo "\n Enter your database password: ";
  654 + $db[ 'password' ] = trim(fgets(STDIN));
  655 + $db[ 'dsn' ] = "pgsql:host={$host};port={$port};dbname={$name}";
  656 + $this->db = $db;
  657 + return $db;
  658 + }
  659 +
  660 + /**
  661 + * Init mysql connection
  662 + *
  663 + * @return array
  664 + */
  665 + private function initMysql(): array
  666 + {
  667 + $db = [
  668 + 'dbtype' => 'mysql',
  669 + ];
  670 + echo "\n Enter your database host: ";
  671 + $host = trim(fgets(STDIN));
  672 + echo "\n Enter your database name: ";
  673 + $name = trim(fgets(STDIN));
  674 + echo "\n Enter your database username: ";
  675 + $db[ 'username' ] = trim(fgets(STDIN));
  676 + echo "\n Enter your database password: ";
  677 + $db[ 'password' ] = trim(fgets(STDIN));
  678 + $db[ 'dsn' ] = "mysql:host={$host};dbname={$name}";
  679 + $this->db = $db;
  680 + return $db;
  681 + }
  682 +
  683 + /**
  684 + * Validate non-interactive db data and fill it for further actions.
  685 + *
  686 + * @return array
  687 + */
  688 + private function validateConnection(): array
  689 + {
  690 + $db = [];
  691 + $dbType = strtolower($this->getParamValue('dbtype'));
  692 + if ($dbType !== 'postgresql' && $dbType !== 'mysql') {
  693 + die( "Supported DB types are postgresql and mysql" );
  694 + }
  695 + if ($dbType === 'postgresql') {
  696 + $host = $this->getParamValue('host') ? : '127.0.0.1';
  697 + $port = $this->getParamValue('port') ? : '5432';
  698 + $db[ 'schema' ] = $this->getParamValue('schema') ? : 'public';
  699 + $name = $this->getParamValue('dbname');
  700 + if (empty( $name )) {
  701 + die( "Database name must be set" );
  702 + }
  703 + $db[ 'dsn' ] = "pgsql:host={$host};port={$port};dbname={$name}";
  704 + if (empty( $username = $this->getParamValue('username') )) {
  705 + die( "Database username must be set" );
  706 + }
  707 + $db[ 'username' ] = $username;
  708 + if (empty( $password = $this->getParamValue('password') )) {
  709 + die( "Database password must be set" );
  710 + }
  711 + $db[ 'password' ] = $password;
  712 + } else {
  713 + $host = $this->getParamValue('host') ? : '127.0.0.1';
  714 + $name = $this->getParamValue('dbname');
  715 + if (empty( $name )) {
  716 + die( "Database name must be set" );
  717 + }
  718 + $db[ 'dsn' ] = "mysql:host={$host};dbname={$name}";
  719 + if (empty( $username = $this->getParamValue('username') )) {
  720 + die( "Database username must be set" );
  721 + }
  722 + $db[ 'username' ] = $username;
  723 + if (empty( $password = $this->getParamValue('password') )) {
  724 + die( "Database password must be set" );
  725 + }
  726 + $db[ 'password' ] = $password;
  727 + }
  728 + $db[ 'dbtype' ] = $dbType;
  729 + $this->db = $db;
  730 + return $db;
  731 + }
  732 +
  733 + /**
  734 + * Copy db connection file accroding to choosen driver
  735 + */
  736 + private function initDb()
  737 + {
  738 + if (!empty( $configPath = $this->environment[ 'setDbConnection' ] )) {
  739 + if (preg_match('/(.*)\/.*/', $configPath, $matches)) {
  740 + $path = $matches[ 1 ];
  741 + } else {
  742 + $this->printError("Unknown error while trying to init database");
  743 + exit( 1 );
  744 + }
  745 + $filename = "db{$this->db['dbtype']}.php";
  746 + $all = !empty( $this->getParamValue('overwrite') ) ? false : true;
  747 + $fullpath = "{$path}/{$filename}";
  748 + if ($this->copyFile("environments/{$filename}", $fullpath, $all)) {
  749 + $this->rewriteDb($fullpath, $configPath);
  750 + }
  751 + }
  752 + }
  753 +
  754 + /**
  755 + * Rewrite params in db config and local config files
  756 + *
  757 + * @param string $path
  758 + * @param string $config
  759 + */
  760 + private function rewriteDb(string $path, string $config)
  761 + {
  762 + $db = $this->db;
  763 + $this->setParam('dsn', $db[ 'dsn' ], $path);
  764 + $this->setParam('username', $db[ 'username' ], $path);
  765 + $this->setParam('password', $db[ 'password' ], $path);
  766 + if ($this->db[ 'dbtype' ] == 'postgresql') {
  767 + $this->setParam('defaultSchema', $db[ 'schema' ], $path);
  768 + }
  769 + $filename = "db{$this->db['dbtype']}.php";
  770 + $this->setParam('db', "require('{$filename}')", $config, true, true);
  771 + $driver = ucfirst($db[ 'dbtype' ]);
  772 + echo $this->formatMessage(
  773 + "Database access file $path was created and filled with configurations for database driver {$driver}",
  774 + [ 'fg-green' ]
  775 + ) . "\n";
  776 + echo $this->formatMessage(
  777 + "Database access file $path was linked to local config file $config",
  778 + [ 'fg-green' ]
  779 + ) . "\n";
  780 + echo $this->formatMessage("Database Access: ", [ 'bg-yellow' ]) . $this->formatMessage(
  781 + $this->db[ 'dsn' ],
  782 + [
  783 + 'bg-yellow',
  784 + 'fg-blue',
  785 + ]
  786 + ) . $this->formatMessage(', username: ', [ 'bg-yellow' ]) . $this->formatMessage(
  787 + $this->db[ 'username' ],
  788 + [
  789 + 'bg-yellow',
  790 + 'fg-blue',
  791 + ]
  792 + ) . "\n";
  793 + echo " Database initialization completed\n";
  794 + echo " =================================\n";
  795 + }
  796 +
  797 + /**
  798 + * Prints error message.
  799 + *
  800 + * @param string $message message
  801 + */
  802 + private function printError(string $message)
  803 + {
  804 + echo "\n " . $this->formatMessage(
  805 + "Error. $message",
  806 + [
  807 + 'fg-red',
  808 + 'bold',
  809 + ]
  810 + ) . " \n";
  811 + }
  812 +
  813 + /**
  814 + * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream.
  815 + * - windows without ansicon
  816 + * - not tty consoles
  817 + *
  818 + * @return boolean true if the stream supports ANSI colors, otherwise false.
  819 + */
  820 + private function ansiColorsSupported(): bool
  821 + {
  822 + return DIRECTORY_SEPARATOR === '\\' ? getenv('ANSICON') !== false || getenv(
  823 + 'ConEmuANSI'
  824 + ) === 'ON' : function_exists('posix_isatty') && @posix_isatty(STDOUT);
  825 + }
  826 +
  827 + /**
  828 + * Get ANSI code of style.
  829 + *
  830 + * @param string $name style name
  831 + *
  832 + * @return integer ANSI code of style.
  833 + */
  834 + private function getStyleCode(string $name): int
  835 + {
  836 + $styles = [
  837 + 'bold' => 1,
  838 + 'fg-black' => 30,
  839 + 'fg-red' => 31,
  840 + 'fg-green' => 32,
  841 + 'fg-yellow' => 33,
  842 + 'fg-blue' => 34,
  843 + 'fg-magenta' => 35,
  844 + 'fg-cyan' => 36,
  845 + 'fg-white' => 37,
  846 + 'bg-black' => 40,
  847 + 'bg-red' => 41,
  848 + 'bg-green' => 42,
  849 + 'bg-yellow' => 43,
  850 + 'bg-blue' => 44,
  851 + 'bg-magenta' => 45,
  852 + 'bg-cyan' => 46,
  853 + 'bg-white' => 47,
  854 + ];
  855 + return $styles[ $name ];
  856 + }
  857 +
  858 + /**
  859 + * Formats message using styles if STDOUT supports it.
  860 + *
  861 + * @param string $message message
  862 + * @param string[] $styles styles
  863 + *
  864 + * @return string formatted message.
  865 + */
  866 + public function formatMessage(string $message, array $styles = []): string
  867 + {
  868 + if (empty( $styles ) || !$this->ansiColorsSupported()) {
  869 + return $message;
  870 + }
  871 + return sprintf(
  872 + "\x1b[%sm",
  873 + implode(
  874 + ';',
  875 + array_map(
  876 + [
  877 + $this,
  878 + 'getStyleCode',
  879 + ],
  880 + $styles
  881 + )
  882 + )
  883 + ) . $message . "\x1b[0m";
  884 + }
  885 +
  886 + /**
  887 + * Inform that an application initialized without database. Exit code 0, means success.
  888 + */
  889 + private function noDatabaseMessage()
  890 + {
  891 + echo $this->formatMessage(
  892 + "\n Attention: ",
  893 + [
  894 + 'bold',
  895 + 'fg-red',
  896 + 'bg-yellow',
  897 + ]
  898 + );
  899 + echo $this->formatMessage(
  900 + "Application initialized without database. Set it manually in {$this->getRoot()}/common/config/main-local.php and run migration",
  901 + [
  902 + 'bold',
  903 + 'bg-yellow',
  904 + ]
  905 + ) . "\n";
  906 + exit( 0 );
  907 + }
  908 +
  909 + /**
  910 + * Perform database migration if input param migrate doesn't set to 'no'
  911 + */
  912 + private function migrate()
  913 + {
  914 + $migrate = $this->getParamValue('migrate');
  915 + if ($migrate == 'no') {
  916 + echo $this->formatMessage(
  917 + "Migration skipped by user. In order to application work correct you will need to run it manually",
  918 + [
  919 + 'bg-yellow',
  920 + 'bold',
  921 + ]
  922 + ) . "\n";
  923 + exit( 0 );
  924 + } elseif ($migrate != 'yes') {
  925 + do {
  926 + echo " Do you want to perform database migration? [yes|no]";
  927 + $answer = trim(fgets(STDIN));
  928 + } while (strncasecmp($answer, 'y', 1) !== 0 && strncasecmp($answer, 'n', 1) !== 0);
  929 + if (strncasecmp($answer, 'n', 1) === 0) {
  930 + echo $this->formatMessage(
  931 + "Migration skipped by user. In order to application work correct you will need to run it manually",
  932 + [
  933 + 'bg-yellow',
  934 + 'bold',
  935 + ]
  936 + ) . "\n";
  937 + exit( 0 );
  938 + }
  939 + }
  940 + echo $this->formatMessage("Migration begins...", [ 'fg-yellow' ]) . "\n";
  941 + $migrationPath = $this->getParamValue('migrationPath');
  942 + if (empty( $migrationPath )) {
  943 + $migrationPath = 'vendor/artweb/artbox-core/migrations';
  944 + }
  945 + $result = exec("php yii migrate --migrationPath=$migrationPath --interactive=0", $output, $return);
  946 + if ($return !== 0) {
  947 + $this->printError("Migration cannot be applied. Run it manually to check the reason");
  948 + exit( 1 );
  949 + }
  950 + $this->writeLine($result);
  951 + foreach ($output as $value) {
  952 + $this->writeLine($value);
  953 + }
  954 + echo $this->formatMessage("Migration ended successfully", [ 'fg-yellow' ]) . "\n";
  955 + }
  956 +
  957 + /**
  958 + * Write line of code followed by new line symbol
  959 + *
  960 + * @param string $string
  961 + */
  962 + private function writeLine(string $string)
  963 + {
  964 + echo $string . "\n";
  965 + }
  966 +
  967 + /**
  968 + * Perform user creation if input param user doesn't set to 'no'
  969 + */
  970 + private function createUser()
  971 + {
  972 + $params = $this->getParams();
  973 + if (!isset( $params[ 'defaultuser' ] )) {
  974 + if ($this->getParamValue('user') == 'no') {
  975 + echo $this->formatMessage(
  976 + "User creation skipped by user. Run command 'php yii user/create' manually to create user.",
  977 + [
  978 + 'bg-yellow',
  979 + 'bold',
  980 + ]
  981 + ) . "\n";
  982 + exit( 0 );
  983 + }
  984 + do {
  985 + echo " Do you want to create user? [yes|no]";
  986 + $answer = trim(fgets(STDIN));
  987 + } while (strncasecmp($answer, 'y', 1) !== 0 && strncasecmp($answer, 'n', 1) !== 0);
  988 + if (strncasecmp($answer, 'n', 1) === 0) {
  989 + echo $this->formatMessage(
  990 + "User creation skipped by user. Run command 'php yii user/create' manually to create user.",
  991 + [
  992 + 'bg-yellow',
  993 + 'bold',
  994 + ]
  995 + ) . "\n";
  996 + exit( 0 );
  997 + }
  998 + echo "\n Enter username: ";
  999 + $username = trim(fgets(STDIN));
  1000 + echo "\n Enter email: ";
  1001 + $email = trim(fgets(STDIN));
  1002 + echo "\n Enter password: ";
  1003 + $password = trim(fgets(STDIN));
  1004 + echo "\n";
  1005 + $result = exec("php yii create/user $username $email $password", $output, $return);
  1006 + } else {
  1007 + $result = exec("php yii create/user", $output, $return);
  1008 + }
  1009 + $this->handleUserCreation($result, $output, $return);
  1010 + }
  1011 +
  1012 + /**
  1013 + * Handle user creation result
  1014 + *
  1015 + * @param string $result
  1016 + * @param array $output
  1017 + * @param int $return
  1018 + */
  1019 + private function handleUserCreation($result, $output, $return)
  1020 + {
  1021 + if ($return !== 0) {
  1022 + $this->printError("User cannot be created. Run 'php yii create/user' manually to check the reason");
  1023 + exit( 1 );
  1024 + }
  1025 + $this->writeLine($result);
  1026 + echo $this->formatMessage("User created successfully", [ 'fg-yellow' ]) . "\n";
  1027 + }
  1028 +
  1029 + /**
  1030 + * Congratulate with successfull installation and optionally open browser
  1031 + */
  1032 + private function congratulate()
  1033 + {
  1034 + echo "\n" . $this->formatMessage(
  1035 + "Congratulations. Artbox Basic has been successfully installed.",
  1036 + [
  1037 + 'fg-yellow',
  1038 + 'bold',
  1039 + ]
  1040 + ) . "\n";
  1041 + $url = $this->getParamValue('o');
  1042 + if (!empty( $url )) {
  1043 + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  1044 + shell_exec("explorer '{$url}'");
  1045 + } else {
  1046 + shell_exec("sensible-browser {$url} > /dev/null 2>/dev/null &");
  1047 + $params = $this->getParams();
  1048 + if (isset( $params[ 'fun' ] )) {
  1049 + echo shell_exec("hollywood");
  1050 + }
  1051 + }
  1052 + }
  1053 + }
  1054 +
  1055 + /**
  1056 + * Check if database connection could be established
  1057 + *
  1058 + * @return bool
  1059 + * @throws \Exception
  1060 + */
  1061 + private function databaseCheck(): bool
  1062 + {
  1063 + $params = $this->getParams();
  1064 + if (isset( $params[ 'checkdb' ] )) {
  1065 + $configPath = $this->environment[ 'setDbConnection' ];
  1066 + if (preg_match('/(.*)\/.*/', $configPath, $matches)) {
  1067 + $path = $matches[ 1 ];
  1068 + } else {
  1069 + $this->printError("Unknown error while trying to check connection");
  1070 + exit( 1 );
  1071 + }
  1072 + $filename = "db{$this->db['dbtype']}.php";
  1073 + $fullpath = "{$path}/{$filename}";
  1074 + exec("php yii check/connection {$fullpath}", $output, $return);
  1075 + if ($return > 0) {
  1076 + if (isset( $params[ 'dbinit' ] )) {
  1077 + throw new Exception("Couldn't connect to the database");
  1078 + }
  1079 + echo $this->printError("Database unavailable. Please choose another database!");
  1080 + return false;
  1081 + }
  1082 + }
  1083 + echo $this->formatMessage(" Database connection successful!", [ 'fg-green' ]) . "\n";
  1084 + return true;
  1085 + }
  1086 + }
  1087 +
0 1088 \ No newline at end of file
... ...
_composer.json 0 → 100644
  1 +{
  2 + "name": "artweb/artbox-basic",
  3 + "description": "Artbox Basic Project Template",
  4 + "keywords": [
  5 + "yii2",
  6 + "cms",
  7 + "artweb",
  8 + "artbox",
  9 + "basic",
  10 + "project template"
  11 + ],
  12 + "homepage": "http://artweb.ua",
  13 + "type": "project",
  14 + "license": "BSD-3-Clause",
  15 + "support": {
  16 + "wiki": "http://www.yiiframework.com/wiki/"
  17 + },
  18 + "minimum-stability": "dev",
  19 + "require": {
  20 + "php": ">=7.0",
  21 + "artweb/artbox-core": "*",
  22 + "yiisoft/yii2": "~2.0",
  23 + "yiisoft/yii2-bootstrap": "~2.0",
  24 + "yiisoft/yii2-swiftmailer": "~2.0",
  25 + "noam148/yii2-image-manager": "~1.0",
  26 + "yiister/yii2-gentelella": "~1.0",
  27 + "yii2tech/filedb": "~1.0",
  28 + "hiqdev/yii2-asset-pnotify": "~2.0",
  29 + "hiqdev/yii2-asset-icheck": "~1.0",
  30 + "google/apiclient": "^2.0"
  31 + },
  32 + "require-dev": {
  33 + "yiisoft/yii2-debug": "~2.0.0",
  34 + "yiisoft/yii2-gii": "~2.0.0",
  35 + "yiisoft/yii2-faker": "~2.0.0",
  36 + "codeception/base": "^2.2.3",
  37 + "codeception/verify": "~0.3.1"
  38 + },
  39 + "config": {
  40 + "process-timeout": 1800
  41 + },
  42 + "extra": {
  43 + "asset-installer-paths": {
  44 + "npm-asset-library": "vendor/npm",
  45 + "bower-asset-library": "vendor/bower"
  46 + }
  47 + },
  48 + "scripts": {
  49 + "post-install-cmd": "php init --env=Development --overwrite=n"
  50 + },
  51 + "autoload": {
  52 + "psr-4": {
  53 + "artbox\\core\\": "artweb/artbox-core/",
  54 + "artbox\\gentelella\\": "artweb/artbox-gentelella/"
  55 + }
  56 + }
  57 +}
... ...
backend/config/main.php
... ... @@ -38,11 +38,12 @@
38 38 'assetManager' => [
39 39 'bundles' => [
40 40 'yiister\gentelella\assets\ThemeAsset' => [
41   - 'sourcePath' => '@backend/assets/',
42   - 'js' => [
  41 + 'basePath' => '@webroot',
  42 + 'baseUrl' => '@web',
  43 + 'js' => [
43 44 'js/custom.js',
44 45 ],
45   - 'css' => [
  46 + 'css' => [
46 47 'css/custom.css',
47 48 ],
48 49 ],
... ...
backend/controllers/SettingsController.php 0 → 100755
  1 +<?php
  2 + namespace backend\controllers;
  3 +
  4 + use common\models\Settings;
  5 + use yii\base\InvalidConfigException;
  6 + use yii\filters\AccessControl;
  7 + use yii\web\Controller;
  8 + use Yii;
  9 +
  10 + /**
  11 + * Class SettingsController
  12 + *
  13 + * @package artbox\core\controllers
  14 + */
  15 + class SettingsController extends Controller
  16 + {
  17 + /**
  18 + * @inheritdoc
  19 + */
  20 + public function behaviors()
  21 + {
  22 + return [
  23 + 'access' => [
  24 + 'class' => AccessControl::className(),
  25 + 'rules' => [
  26 + [
  27 + 'actions' => [
  28 + 'login',
  29 + 'error',
  30 + ],
  31 + 'allow' => true,
  32 + ],
  33 + [
  34 + 'actions' => [
  35 + 'logout',
  36 + 'index',
  37 + ],
  38 + 'allow' => true,
  39 + 'roles' => [ '@' ],
  40 + ],
  41 + ],
  42 + ],
  43 + ];
  44 + }
  45 + /**
  46 + * @inheritdoc
  47 + */
  48 + public function getViewPath()
  49 + {
  50 + return \Yii::getAlias('@artbox/core/views/settings');
  51 + }
  52 +
  53 + /**
  54 + * Display site settings page
  55 + *
  56 + * @return string|\yii\web\Response
  57 + */
  58 + public function actionIndex()
  59 + {
  60 + $model = $this->findSettings();
  61 +
  62 + if ($model->load(Yii::$app->request->post()) && $model->save()) {
  63 + Yii::$app->session->setFlash('success', 'Settings saved');
  64 +
  65 + return $this->goHome();
  66 + }
  67 +
  68 + return $this->render(
  69 + 'settings',
  70 + [
  71 + 'model' => $model,
  72 + ]
  73 + );
  74 + }
  75 +
  76 + /**
  77 + * Find site settings
  78 + *
  79 + * @return \yii2tech\filedb\ActiveRecord
  80 + * @throws \yii\base\InvalidConfigException
  81 + */
  82 + public function findSettings()
  83 + {
  84 + if ($model = Settings::find()
  85 + ->one()
  86 + ) {
  87 + return $model;
  88 + } else {
  89 + throw new InvalidConfigException('Settings file not found');
  90 + }
  91 + }
  92 + }
  93 +
0 94 \ No newline at end of file
... ...
backend/controllers/SiteController.php
1 1 <?php
2   -namespace backend\controllers;
3   -
4   -use Yii;
5   -use yii\web\Controller;
6   -use yii\filters\VerbFilter;
7   -use yii\filters\AccessControl;
8   -use common\models\LoginForm;
9   -
10   -/**
11   - * Site controller
12   - */
13   -class SiteController extends Controller
14   -{
  2 + namespace backend\controllers;
  3 +
  4 + use Yii;
  5 + use yii\web\Controller;
  6 + use yii\filters\VerbFilter;
  7 + use yii\filters\AccessControl;
  8 + use common\models\LoginForm;
  9 +
15 10 /**
16   - * @inheritdoc
  11 + * Site controller
17 12 */
18   - public function behaviors()
  13 + class SiteController extends Controller
19 14 {
20   - return [
21   - 'access' => [
22   - 'class' => AccessControl::className(),
23   - 'rules' => [
24   - [
25   - 'actions' => ['login', 'error'],
26   - 'allow' => true,
27   - ],
28   - [
29   - 'actions' => [
30   - 'logout',
31   - 'index',
32   - 'analytic',
  15 + /**
  16 + * @inheritdoc
  17 + */
  18 + public function behaviors()
  19 + {
  20 + return [
  21 + 'access' => [
  22 + 'class' => AccessControl::className(),
  23 + 'rules' => [
  24 + [
  25 + 'actions' => [
  26 + 'login',
  27 + 'error',
  28 + ],
  29 + 'allow' => true,
  30 + ],
  31 + [
  32 + 'actions' => [
  33 + 'logout',
  34 + 'index',
  35 + 'analytic',
  36 + ],
  37 + 'allow' => true,
  38 + 'roles' => [ '@' ],
33 39 ],
34   - 'allow' => true,
35   - 'roles' => ['@'],
36 40 ],
37 41 ],
38   - ],
39   - 'verbs' => [
40   - 'class' => VerbFilter::className(),
41   - 'actions' => [
42   - 'logout' => ['post'],
  42 + 'verbs' => [
  43 + 'class' => VerbFilter::className(),
  44 + 'actions' => [
  45 + 'logout' => [ 'post' ],
  46 + ],
43 47 ],
44   - ],
45   - ];
46   - }
47   -
48   - /**
49   - * @inheritdoc
50   - */
51   - public function actions()
52   - {
53   - return [
54   - 'error' => [
55   - 'class' => 'yii\web\ErrorAction',
56   - ],
57   - ];
58   - }
59   -
60   - /**
61   - * Displays homepage.
62   - *
63   - * @return string
64   - */
65   - public function actionIndex()
66   - {
67   - return $this->render('index');
68   - }
69   -
70   - /**
71   - * Login action.
72   - *
73   - * @return string
74   - */
75   - public function actionLogin()
76   - {
77   - if (!Yii::$app->user->isGuest) {
  48 + ];
  49 + }
  50 +
  51 + /**
  52 + * @inheritdoc
  53 + */
  54 + public function actions()
  55 + {
  56 + return [
  57 + 'error' => [
  58 + 'class' => 'yii\web\ErrorAction',
  59 + ],
  60 + ];
  61 + }
  62 +
  63 + /**
  64 + * Displays homepage.
  65 + *
  66 + * @return string
  67 + */
  68 + public function actionIndex()
  69 + {
  70 + return $this->render('index');
  71 + }
  72 +
  73 + /**
  74 + * Login action.
  75 + *
  76 + * @return string
  77 + */
  78 + public function actionLogin()
  79 + {
  80 + if (!Yii::$app->user->isGuest) {
  81 + return $this->goHome();
  82 + }
  83 +
  84 + $model = new LoginForm();
  85 + if ($model->load(Yii::$app->request->post()) && $model->login()) {
  86 + return $this->goBack();
  87 + } else {
  88 + return $this->renderPartial(
  89 + 'login',
  90 + [
  91 + 'model' => $model,
  92 + ]
  93 + );
  94 + }
  95 + }
  96 +
  97 + /**
  98 + * Logout action.
  99 + *
  100 + * @return string
  101 + */
  102 + public function actionLogout()
  103 + {
  104 + Yii::$app->user->logout();
  105 +
78 106 return $this->goHome();
79 107 }
80   -
81   - $model = new LoginForm();
82   - if ($model->load(Yii::$app->request->post()) && $model->login()) {
83   - return $this->goBack();
84   - } else {
85   - return $this->renderPartial('login', [
86   - 'model' => $model,
87   - ]);
  108 +
  109 + public function actionAnalytic()
  110 + {
  111 + return $this->renderPartial('analytic');
88 112 }
89 113 }
90   -
91   - /**
92   - * Logout action.
93   - *
94   - * @return string
95   - */
96   - public function actionLogout()
97   - {
98   - Yii::$app->user->logout();
99   -
100   - return $this->goHome();
101   - }
102   -
103   - public function actionAnalytic()
104   - {
105   - return $this->renderPartial('analytic');
106   - }
107   -}
... ...
backend/views/layouts/main.php
... ... @@ -7,25 +7,24 @@
7 7  
8 8 use artbox\core\assets\ArtboxCoreAsset;
9 9 use artbox\core\models\User;
  10 + use artbox\core\models\UserData;
10 11 use artbox\core\widgets\FeedbackWidget;
11 12 use artbox\core\widgets\FlashWidget;
12   - use hiqdev\assets\icheck\iCheckAsset;
13   - use hiqdev\assets\pnotify\PNotifyAsset;
14 13 use yii\bootstrap\Html;
15 14 use yii\web\UrlManager;
16 15 use yii\web\View;
17 16 use yii\widgets\Breadcrumbs;
18 17 use yiister\gentelella\widgets\Menu;
19 18  
20   - yiister\gentelella\assets\Asset::register($this);
21   - PNotifyAsset::register($this);
22 19 ArtboxCoreAsset::register($this);
23   - iCheckAsset::register($this);
24 20  
25 21 /**
26 22 * @var User $user
27 23 */
28 24 $user = \Yii::$app->user->identity;
  25 + /**
  26 + * @var UserData $userData
  27 + */
29 28 $userData = $user->ensureExistance();
30 29 ?>
31 30 <?php $this->beginPage(); ?>
... ...
backend/views/settings/settings.php 0 → 100755
  1 +<?php
  2 + /**
  3 + * @var View $this
  4 + * @var Settings $model
  5 + */
  6 +
  7 + use common\models\Settings;
  8 + use artbox\gentelella\widgets\XPanel;
  9 + use yii\bootstrap\ActiveForm;
  10 + use yii\bootstrap\Html;
  11 + use yii\web\View;
  12 +
  13 + $this->title = 'Settings';
  14 +
  15 + $this->params[ 'breadcrumbs' ][] = $this->title;
  16 +?>
  17 +
  18 +<?php $panel = XPanel::begin(
  19 + [
  20 + 'title' => $this->title,
  21 + 'toolbar' => false,
  22 + ]
  23 +); ?>
  24 +
  25 +<div class="settings-form">
  26 +
  27 + <?php
  28 + $form = ActiveForm::begin();
  29 +
  30 + echo $form->field($model, 'id')
  31 + ->textInput();
  32 +
  33 + echo $form->field($model, 'name')
  34 + ->textInput();
  35 +
  36 + echo $form->field($model, 'description')
  37 + ->textInput();
  38 +
  39 + echo $form->field($model, 'analytics')
  40 + ->textarea(
  41 + [
  42 + 'rows' => 11,
  43 + ]
  44 + );
  45 +
  46 + echo Html::submitButton(
  47 + 'Save',
  48 + [
  49 + 'class' => 'btn btn-primary',
  50 + ]
  51 + );
  52 + ActiveForm::end();
  53 + ?>
  54 +
  55 +</div>
  56 +
  57 +<?php $panel::end(); ?>
... ...
backend/views/site/error.php
1 1 <?php
2   -
3   -/* @var $this yii\web\View */
4   -/* @var $name string */
5   -/* @var $message string */
6   -/* @var $exception Exception */
7   -
8   -use yii\helpers\Html;
9   -
10   -$this->title = $name;
  2 + use yii\helpers\Html;
  3 +
  4 + /**
  5 + * @var $this yii\web\View
  6 + * @var $name string
  7 + * @var $message string
  8 + * @var $exception Exception
  9 + */
  10 +
  11 + $this->title = $name;
11 12 ?>
12 13 <div class="site-error">
13   -
  14 +
14 15 <h1><?= Html::encode($this->title) ?></h1>
15   -
  16 +
16 17 <div class="alert alert-danger">
17 18 <?= nl2br(Html::encode($message)) ?>
18 19 </div>
19   -
  20 +
20 21 <p>
21 22 The above error occurred while the Web server was processing your request.
22 23 </p>
... ...
backend/views/site/login.php
... ... @@ -3,8 +3,10 @@
3 3 /**
4 4 * @var string $content
5 5 * @var \yii\web\View $this
  6 + * @var LoginForm $model
6 7 */
7 8  
  9 + use common\models\LoginForm;
8 10 use hiqdev\assets\icheck\iCheckAsset;
9 11 use yii\helpers\Html;
10 12 use yii\web\View;
... ... @@ -26,72 +28,68 @@ JS;
26 28 <?php $this->beginPage(); ?>
27 29 <!DOCTYPE html>
28 30 <html lang="<?= Yii::$app->language ?>">
29   -<head>
30   - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
31   - <meta charset="<?= Yii::$app->charset ?>"/>
32   - <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
33   - <meta name="viewport" content="width=device-width, initial-scale=1"/>
34   - <?= Html::csrfMetaTags() ?>
35   - <title><?= Html::encode($this->title) ?></title>
36   - <?php $this->head() ?>
37   - <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
38   - <!--[if lt IE 9]>
39   - <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
40   - <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
41   - <![endif]-->
42   -</head>
43   -<body>
44   -<?php $this->beginBody(); ?>
45   -<div class="container" style="background-color: #F7F7F7; height: 100%">
46   - <div class="row" style="margin-top: 10%">
47   - <div class="col-md-4 col-md-offset-4">
48   -
49   -
50   - <div class="site-login x_panel">
51   - <div class="x_title">
52   - <h1><?= Html::encode($this->title) ?></h1>
53   -
54   - <p>Please fill out the following fields to login:</p>
55   - </div>
56   - <div class="row">
57   - <div>
58   - <?php $form = ActiveForm::begin(
59   - [
60   - 'id' => 'login-form',
61   - 'validateOnBlur' => false,
62   - ]
63   - ); ?>
64   -
65   - <?= $form->field($model, 'username')
66   - ->textInput([ 'autofocus' => true ]) ?>
67   -
68   - <?= $form->field($model, 'password')
69   - ->passwordInput() ?>
70   -
71   - <?= $form->field($model, 'rememberMe')
72   - ->checkbox() ?>
73   -
74   - <div class="form-group">
75   - <?= Html::submitButton('Login',
76   - [
77   - 'class' => 'btn btn-default',
78   - 'name' => 'login-button',
79   - ]
80   - ) ?>
  31 + <head>
  32 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  33 + <meta charset="<?= Yii::$app->charset ?>"/>
  34 + <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
  35 + <meta name="viewport" content="width=device-width, initial-scale=1"/>
  36 + <?= Html::csrfMetaTags() ?>
  37 + <title><?= Html::encode($this->title) ?></title>
  38 + <?php $this->head() ?>
  39 + </head>
  40 + <body>
  41 + <?php $this->beginBody(); ?>
  42 + <div class="container" style="background-color: #F7F7F7; height: 100%">
  43 + <div class="row" style="margin-top: 10%">
  44 + <div class="col-md-4 col-md-offset-4">
  45 +
  46 +
  47 + <div class="site-login x_panel">
  48 + <div class="x_title">
  49 + <h1><?= Html::encode($this->title) ?></h1>
  50 +
  51 + <p>Please fill out the following fields to login:</p>
  52 + </div>
  53 + <div class="row">
  54 + <div>
  55 + <?php $form = ActiveForm::begin(
  56 + [
  57 + 'id' => 'login-form',
  58 + 'validateOnBlur' => false,
  59 + ]
  60 + ); ?>
  61 +
  62 + <?= $form->field($model, 'username')
  63 + ->textInput([ 'autofocus' => true ]) ?>
  64 +
  65 + <?= $form->field($model, 'password')
  66 + ->passwordInput() ?>
  67 +
  68 + <?= $form->field($model, 'rememberMe')
  69 + ->checkbox() ?>
  70 +
  71 + <div class="form-group">
  72 + <?= Html::submitButton(
  73 + 'Login',
  74 + [
  75 + 'class' => 'btn btn-default',
  76 + 'name' => 'login-button',
  77 + ]
  78 + ) ?>
  79 + </div>
  80 +
  81 + <?php ActiveForm::end(); ?>
  82 + </div>
  83 + </div>
  84 + </div>
  85 +
  86 +
  87 + </div>
81 88 </div>
82   -
83   - <?php ActiveForm::end(); ?>
84   - </div>
  89 +
85 90 </div>
86   - </div>
87   -
88   -
89   - </div>
90   - </div>
91   -
92   -</div>
93   -<?php $this->endBody(); ?>
94   -</body>
  91 + <?php $this->endBody(); ?>
  92 + </body>
95 93 </html>
96 94 <?php $this->endPage(); ?>
97 95  
... ...
backend/assets/css/custom.css renamed to backend/web/css/custom.css
backend/assets/js/custom.js renamed to backend/web/js/custom.js
common/config/.gitignore
1 1 main-local.php
  2 +db*
2 3 params-local.php
3 4 test-local.php
4 5 settings.php
5 6 \ No newline at end of file
... ...
common/models/Settings.php 0 → 100755
  1 +<?php
  2 + namespace common\models;
  3 +
  4 + use yii2tech\filedb\ActiveRecord;
  5 + use Yii;
  6 +
  7 + /**
  8 + * Class Settings
  9 + *
  10 + * @package artbox\core\models
  11 + * @property string $name
  12 + * @property string $id
  13 + * @property string $description
  14 + * @property string $analytics
  15 + */
  16 + class Settings extends ActiveRecord
  17 + {
  18 + /**
  19 + * @inheritdoc
  20 + */
  21 + public function rules()
  22 + {
  23 + return [
  24 + [
  25 + [
  26 + 'name',
  27 + 'description',
  28 + 'id',
  29 + 'analytics',
  30 + ],
  31 + 'string',
  32 + ],
  33 + ];
  34 + }
  35 +
  36 + /**
  37 + * @inheritdoc
  38 + */
  39 + public static function fileName()
  40 + {
  41 + return 'settings';
  42 + }
  43 +
  44 + /**
  45 + * @inheritdoc
  46 + */
  47 + public function attributeLabels()
  48 + {
  49 + return [
  50 + 'id' => Yii::t('core', 'ID'),
  51 + 'name' => Yii::t('core', 'Name'),
  52 + 'description' => Yii::t('core', 'Description'),
  53 + 'analytics' => Yii::t('core', 'Google Analytics Code'),
  54 + ];
  55 + }
  56 +
  57 + /**
  58 + * Get Settings model instance
  59 + *
  60 + * @return Settings
  61 + */
  62 + public static function getInstance()
  63 + {
  64 + return self::findOne([ 'id' => 1 ]);
  65 + }
  66 + }
  67 +
0 68 \ No newline at end of file
... ...
composer.json
1 1 {
2   - "name": "yiisoft/yii2-app-advanced",
3   - "description": "Yii 2 Advanced Project Template",
  2 + "name": "artweb/artbox-basic",
  3 + "description": "Artbox Basic Project Template",
4 4 "keywords": [
5 5 "yii2",
6   - "framework",
7   - "advanced",
  6 + "cms",
  7 + "artweb",
  8 + "artbox",
  9 + "basic",
8 10 "project template"
9 11 ],
10   - "homepage": "http://www.yiiframework.com/",
  12 + "homepage": "http://artweb.ua",
11 13 "type": "project",
12 14 "license": "BSD-3-Clause",
13 15 "support": {
14   - "issues": "https://github.com/yiisoft/yii2/issues?state=open",
15   - "forum": "http://www.yiiframework.com/forum/",
16   - "wiki": "http://www.yiiframework.com/wiki/",
17   - "irc": "irc://irc.freenode.net/yii",
18   - "source": "https://github.com/yiisoft/yii2"
  16 + "wiki": "http://www.yiiframework.com/wiki/"
19 17 },
20   - "minimum-stability": "stable",
  18 + "minimum-stability": "dev",
21 19 "require": {
22   - "php": ">=5.4.0",
23   - "yiisoft/yii2": "~2.0.6",
24   - "yiisoft/yii2-bootstrap": "~2.0.0",
25   - "yiisoft/yii2-swiftmailer": "~2.0.0",
26   - "insolita/yii2-migration-generator": "~2.2",
  20 + "php": ">=7.0",
  21 + "artweb/artbox-core": "*",
  22 + "yiisoft/yii2": "~2.0",
  23 + "yiisoft/yii2-bootstrap": "~2.0",
  24 + "yiisoft/yii2-swiftmailer": "~2.0",
  25 + "noam148/yii2-image-manager": "~1.0",
27 26 "yiister/yii2-gentelella": "~1.0",
28   - "hiqdev/yii2-asset-icheck": "1.0.2.5",
29   - "noam148/yii2-image-manager": "*",
30   - "yii2tech/filedb": "^1.0",
31   - "hiqdev/yii2-asset-pnotify": "^2.1",
32   - "yiisoft/yii2-imagine": "*",
33   - "2amigos/yii2-tinymce-widget": "*",
34   - "google/apiclient": "^2.0",
35   - "2amigos/yii2-highcharts-widget": "~1.0"
  27 + "yii2tech/filedb": "~1.0",
  28 + "hiqdev/yii2-asset-pnotify": "~2.0",
  29 + "hiqdev/yii2-asset-icheck": "~1.0",
  30 + "google/apiclient": "^2.0"
36 31 },
37 32 "require-dev": {
38 33 "yiisoft/yii2-debug": "~2.0.0",
... ... @@ -51,12 +46,16 @@
51 46 }
52 47 },
53 48 "scripts": {
54   - "post-install-cmd": "php init --env=Development --overwrite=n"
  49 + "post-install-cmd": "php init --env=Development --overwrite=All --dbinit --dbtype=postgresql --dbname=artbox_basic --username=postgres --password=postgres --migrationPath=artweb/artbox-core/migrations --migrate=yes --defaultuser --checkdb"
55 50 },
56   - "autoload": {
57   - "psr-4": {
58   - "artbox\\core\\": "artweb/artbox-core/",
59   - "artbox\\gentelella\\": "artweb/artbox-gentelella/"
  51 + "repositories": [
  52 + {
  53 + "type": "vsc",
  54 + "url": "git@gitlab.artweb.com.ua:yarik.nechyporuk/artbox-core.git"
  55 + },
  56 + {
  57 + "type": "vsc",
  58 + "url": "git@gitlab.artweb.com.ua:yarik.nechyporuk/artbox-gentelella.git"
60 59 }
61   - }
  60 + ]
62 61 }
... ...
console/controllers/CheckController.php 0 → 100644
  1 +<?php
  2 + namespace console\controllers;
  3 +
  4 + use yii\console\Controller;
  5 + use yii\db\Connection;
  6 + use yii\db\Exception;
  7 + use yii\helpers\ArrayHelper;
  8 +
  9 + /**
  10 + * Class CheckController
  11 + *
  12 + * @package console\controllers
  13 + */
  14 + class CheckController extends Controller
  15 + {
  16 + public function actionConnection($path)
  17 + {
  18 + $connection = \Yii::createObject(require( $path ));
  19 + try {
  20 + $connection->open();
  21 + } catch (Exception $exception) {
  22 + exit( 1 );
  23 + }
  24 + exit( 0 );
  25 + }
  26 + }
0 27 \ No newline at end of file
... ...
console/controllers/CreateController.php
... ... @@ -12,18 +12,30 @@
12 12 */
13 13 class CreateController extends Controller
14 14 {
15   - public function actionUser()
  15 + public function actionUser($username = null, $email = null, $password = null)
16 16 {
17   - $user = new User();
18   - $user->username = 'admin';
19   - $user->email = 'admin@example.com';
20   - $user->setPassword('admin321');
  17 + $username = $username ? : 'admin';
  18 + $user = User::find()
  19 + ->where([ 'username' => $username ])
  20 + ->one();
  21 + if (empty( $user )) {
  22 + $user = new User();
  23 + $user->username = $username;
  24 + }
  25 + $user->email = $email ? : 'admin@example.com';
  26 + $user->setPassword($password ? : 'admin321');
21 27 $user->generateAuthKey();
22 28  
23 29 if ($user->save()) {
24   - $this->stdout('User created' . "\n", Console::FG_GREEN);
  30 + if ($user->isNewRecord) {
  31 + $this->stdout('User created' . "\n", Console::FG_GREEN);
  32 + } else {
  33 + $this->stdout('User updated' . "\n", Console::FG_GREEN);
  34 + }
25 35 } else {
26 36 $this->stdout('Error!' . "\n", Console::FG_RED);
  37 + return self::EXIT_CODE_ERROR;
27 38 }
  39 + return self::EXIT_CODE_NORMAL;
28 40 }
29 41 }
30 42 \ No newline at end of file
... ...
environments/dbmysql.php 0 → 100644
  1 +<?php
  2 + return [
  3 + 'class' => 'yii\db\Connection',
  4 + 'dsn' => '',
  5 + 'username' => '',
  6 + 'password' => '',
  7 + 'charset' => 'utf8',
  8 + ];
  9 + //mysql:host=localhost;dbname=yii2advanced
0 10 \ No newline at end of file
... ...
environments/dbpostgresql.php 0 → 100644
  1 +<?php
  2 + return [
  3 + 'class' => 'yii\db\Connection',
  4 + 'dsn' => '',
  5 + 'username' => '',
  6 + 'password' => '',
  7 + 'charset' => 'utf8',
  8 + 'schemaMap' => [
  9 + 'pgsql' => [
  10 + 'class' => 'yii\db\pgsql\Schema',
  11 + 'defaultSchema' => '',
  12 + ],
  13 + ],
  14 + ];
  15 + //DSN: pgsql:host=127.0.0.1;port=5432;dbname=name
0 16 \ No newline at end of file
... ...
environments/dev/common/config/main-local.php
1 1 <?php
2 2 return [
3 3 'components' => [
4   - 'db' => [
5   - 'class' => 'yii\db\Connection',
6   - 'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
7   - 'username' => 'root',
8   - 'password' => '',
9   - 'charset' => 'utf8',
10   - ],
  4 + 'db' => '',
11 5 'mailer' => [
12 6 'class' => 'yii\swiftmailer\Mailer',
13 7 'viewPath' => '@common/mail',
... ...
environments/index.php
... ... @@ -30,14 +30,14 @@
30 30 */
31 31 return [
32 32 'Development' => [
33   - 'path' => 'dev',
34   - 'setWritable' => [
  33 + 'path' => 'dev',
  34 + 'setWritable' => [
35 35 'backend/runtime',
36 36 'backend/web/assets',
37 37 'frontend/runtime',
38 38 'frontend/web/assets',
39 39 ],
40   - 'setExecutable' => [
  40 + 'setExecutable' => [
41 41 'yii',
42 42 'yii_test',
43 43 ],
... ... @@ -45,21 +45,23 @@ return [
45 45 'backend/config/main-local.php',
46 46 'frontend/config/main-local.php',
47 47 ],
  48 + 'setDbConnection' => 'common/config/main-local.php',
48 49 ],
49 50 'Production' => [
50   - 'path' => 'prod',
51   - 'setWritable' => [
  51 + 'path' => 'prod',
  52 + 'setWritable' => [
52 53 'backend/runtime',
53 54 'backend/web/assets',
54 55 'frontend/runtime',
55 56 'frontend/web/assets',
56 57 ],
57   - 'setExecutable' => [
  58 + 'setExecutable' => [
58 59 'yii',
59 60 ],
60 61 'setCookieValidationKey' => [
61 62 'backend/config/main-local.php',
62 63 'frontend/config/main-local.php',
63 64 ],
  65 + 'setDbConnection' => 'common/config/main-local.php',
64 66 ],
65 67 ];
... ...
environments/prod/common/config/main-local.php
1 1 <?php
2 2 return [
3 3 'components' => [
4   - 'db' => [
5   - 'class' => 'yii\db\Connection',
6   - 'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
7   - 'username' => 'root',
8   - 'password' => '',
9   - 'charset' => 'utf8',
10   - ],
  4 + 'db' => '',
11 5 'mailer' => [
12 6 'class' => 'yii\swiftmailer\Mailer',
13 7 'viewPath' => '@common/mail',
... ...
frontend/views/layouts/main.php
... ... @@ -4,7 +4,7 @@
4 4 /* @var $content string */
5 5  
6 6 use artbox\core\components\SeoComponent;
7   - use artbox\core\models\Settings;
  7 + use common\models\Settings;
8 8 use artbox\core\models\User;
9 9 use yii\helpers\Html;
10 10 use yii\bootstrap\Nav;
... ... @@ -31,7 +31,7 @@
31 31 <meta charset="<?= Yii::$app->charset ?>">
32 32 <meta name="viewport" content="width=device-width, initial-scale=1">
33 33 <?= Html::csrfMetaTags() ?>
34   - <title><?= Html::encode($seo->title) ?></title>
  34 + <title><?= Html::encode($seo->title) ?></title>
35 35 <?php $this->head() ?>
36 36 </head>
37 37 <body>
... ...
1 1 #!/usr/bin/env php
2 2 <?php
3   -/**
4   - * Yii Application Initialization Tool
5   - *
6   - * In order to run in non-interactive mode:
7   - *
8   - * init --env=Development --overwrite=n
9   - *
10   - * @author Alexander Makarov <sam@rmcreative.ru>
11   - *
12   - * @link http://www.yiiframework.com/
13   - * @copyright Copyright (c) 2008 Yii Software LLC
14   - * @license http://www.yiiframework.com/license/
15   - */
16   -
17   -if (!extension_loaded('openssl')) {
18   - die('The OpenSSL PHP extension is required by Yii2.');
19   -}
20   -
21   -$params = getParams();
22   -$root = str_replace('\\', '/', __DIR__);
23   -$envs = require("$root/environments/index.php");
24   -$envNames = array_keys($envs);
25   -
26   -echo "Yii Application Initialization Tool v1.0\n\n";
27   -
28   -$envName = null;
29   -if (empty($params['env']) || $params['env'] === '1') {
30   - echo "Which environment do you want the application to be initialized in?\n\n";
31   - foreach ($envNames as $i => $name) {
32   - echo " [$i] $name\n";
33   - }
34   - echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
35   - $answer = trim(fgets(STDIN));
36   -
37   - if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
38   - echo "\n Quit initialization.\n";
39   - exit(0);
40   - }
41   -
42   - if (isset($envNames[$answer])) {
43   - $envName = $envNames[$answer];
44   - }
45   -} else {
46   - $envName = $params['env'];
47   -}
48   -
49   -if (!in_array($envName, $envNames)) {
50   - $envsList = implode(', ', $envNames);
51   - echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n";
52   - exit(2);
53   -}
54   -
55   -$env = $envs[$envName];
56   -
57   -if (empty($params['env'])) {
58   - echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] ";
59   - $answer = trim(fgets(STDIN));
60   - if (strncasecmp($answer, 'y', 1)) {
61   - echo "\n Quit initialization.\n";
62   - exit(0);
63   - }
64   -}
65   -
66   -echo "\n Start initialization ...\n\n";
67   -$files = getFileList("$root/environments/{$env['path']}");
68   -if (isset($env['skipFiles'])) {
69   - $skipFiles = $env['skipFiles'];
70   - array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; });
71   - $files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists')));
72   -}
73   -$all = false;
74   -foreach ($files as $file) {
75   - if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) {
76   - break;
77   - }
78   -}
79   -
80   -$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
81   -foreach ($callbacks as $callback) {
82   - if (!empty($env[$callback])) {
83   - $callback($root, $env[$callback]);
84   - }
85   -}
86   -
87   -echo "\n ... initialization completed.\n\n";
88   -
89   -function getFileList($root, $basePath = '')
90   -{
91   - $files = [];
92   - $handle = opendir($root);
93   - while (($path = readdir($handle)) !== false) {
94   - if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
95   - continue;
96   - }
97   - $fullPath = "$root/$path";
98   - $relativePath = $basePath === '' ? $path : "$basePath/$path";
99   - if (is_dir($fullPath)) {
100   - $files = array_merge($files, getFileList($fullPath, $relativePath));
101   - } else {
102   - $files[] = $relativePath;
103   - }
104   - }
105   - closedir($handle);
106   - return $files;
107   -}
108   -
109   -function copyFile($root, $source, $target, &$all, $params)
110   -{
111   - if (!is_file($root . '/' . $source)) {
112   - echo " skip $target ($source not exist)\n";
113   - return true;
114   - }
115   - if (is_file($root . '/' . $target)) {
116   - if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
117   - echo " unchanged $target\n";
118   - return true;
119   - }
120   - if ($all) {
121   - echo " overwrite $target\n";
122   - } else {
123   - echo " exist $target\n";
124   - echo " ...overwrite? [Yes|No|All|Quit] ";
125   -
126   -
127   - $answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));
128   - if (!strncasecmp($answer, 'q', 1)) {
129   - return false;
130   - } else {
131   - if (!strncasecmp($answer, 'y', 1)) {
132   - echo " overwrite $target\n";
133   - } else {
134   - if (!strncasecmp($answer, 'a', 1)) {
135   - echo " overwrite $target\n";
136   - $all = true;
137   - } else {
138   - echo " skip $target\n";
139   - return true;
140   - }
141   - }
142   - }
143   - }
144   - file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
145   - return true;
146   - }
147   - echo " generate $target\n";
148   - @mkdir(dirname($root . '/' . $target), 0777, true);
149   - file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
150   - return true;
151   -}
152   -
153   -function getParams()
154   -{
155   - $rawParams = [];
156   - if (isset($_SERVER['argv'])) {
157   - $rawParams = $_SERVER['argv'];
158   - array_shift($rawParams);
159   - }
160   -
161   - $params = [];
162   - foreach ($rawParams as $param) {
163   - if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
164   - $name = $matches[1];
165   - $params[$name] = isset($matches[3]) ? $matches[3] : true;
166   - } else {
167   - $params[] = $param;
168   - }
169   - }
170   - return $params;
171   -}
172   -
173   -function setWritable($root, $paths)
174   -{
175   - foreach ($paths as $writable) {
176   - if (is_dir("$root/$writable")) {
177   - if (@chmod("$root/$writable", 0777)) {
178   - echo " chmod 0777 $writable\n";
179   - } else {
180   - printError("Operation chmod not permitted for directory $writable.");
181   - }
182   - } else {
183   - printError("Directory $writable does not exist.");
184   - }
185   - }
186   -}
187   -
188   -function setExecutable($root, $paths)
189   -{
190   - foreach ($paths as $executable) {
191   - if (file_exists("$root/$executable")) {
192   - if (@chmod("$root/$executable", 0755)) {
193   - echo " chmod 0755 $executable\n";
194   - } else {
195   - printError("Operation chmod not permitted for $executable.");
196   - }
197   - } else {
198   - printError("$executable does not exist.");
199   - }
200   - }
201   -}
202   -
203   -function setCookieValidationKey($root, $paths)
204   -{
205   - foreach ($paths as $file) {
206   - echo " generate cookie validation key in $file\n";
207   - $file = $root . '/' . $file;
208   - $length = 32;
209   - $bytes = openssl_random_pseudo_bytes($length);
210   - $key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
211   - $content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
212   - file_put_contents($file, $content);
213   - }
214   -}
215   -
216   -function createSymlink($root, $links)
217   -{
218   - foreach ($links as $link => $target) {
219   - //first removing folders to avoid errors if the folder already exists
220   - @rmdir($root . "/" . $link);
221   - //next removing existing symlink in order to update the target
222   - if (is_link($root . "/" . $link)) {
223   - @unlink($root . "/" . $link);
224   - }
225   - if (@symlink($root . "/" . $target, $root . "/" . $link)) {
226   - echo " symlink $root/$target $root/$link\n";
227   - } else {
228   - printError("Cannot create symlink $root/$target $root/$link.");
229   - }
230   - }
231   -}
232   -
233   -/**
234   - * Prints error message.
235   - * @param string $message message
236   - */
237   -function printError($message)
238   -{
239   - echo "\n " . formatMessage("Error. $message", ['fg-red']) . " \n";
240   -}
241   -
242   -/**
243   - * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream.
244   - *
245   - * - windows without ansicon
246   - * - not tty consoles
247   - *
248   - * @return boolean true if the stream supports ANSI colors, otherwise false.
249   - */
250   -function ansiColorsSupported()
251   -{
252   - return DIRECTORY_SEPARATOR === '\\'
253   - ? getenv('ANSICON') !== false || getenv('ConEmuANSI') === 'ON'
254   - : function_exists('posix_isatty') && @posix_isatty(STDOUT);
255   -}
256   -
257   -/**
258   - * Get ANSI code of style.
259   - * @param string $name style name
260   - * @return integer ANSI code of style.
261   - */
262   -function getStyleCode($name)
263   -{
264   - $styles = [
265   - 'bold' => 1,
266   - 'fg-black' => 30,
267   - 'fg-red' => 31,
268   - 'fg-green' => 32,
269   - 'fg-yellow' => 33,
270   - 'fg-blue' => 34,
271   - 'fg-magenta' => 35,
272   - 'fg-cyan' => 36,
273   - 'fg-white' => 37,
274   - 'bg-black' => 40,
275   - 'bg-red' => 41,
276   - 'bg-green' => 42,
277   - 'bg-yellow' => 43,
278   - 'bg-blue' => 44,
279   - 'bg-magenta' => 45,
280   - 'bg-cyan' => 46,
281   - 'bg-white' => 47,
282   - ];
283   - return $styles[$name];
284   -}
285   -
286   -/**
287   - * Formats message using styles if STDOUT supports it.
288   - * @param string $message message
289   - * @param string[] $styles styles
290   - * @return string formatted message.
291   - */
292   -function formatMessage($message, $styles)
293   -{
294   - if (empty($styles) || !ansiColorsSupported()) {
295   - return $message;
296   - }
297   -
298   - return sprintf("\x1b[%sm", implode(';', array_map('getStyleCode', $styles))) . $message . "\x1b[0m";
299   -}
  3 + /**
  4 + * Yii Application Initialization Tool
  5 + * In order to run in non-interactive mode:
  6 + * init --env=Development --overwrite=n
  7 + *
  8 + * @author Alexander Makarov <sam@rmcreative.ru>
  9 + * @link http://www.yiiframework.com/
  10 + * @copyright Copyright (c) 2008 Yii Software LLC
  11 + * @license http://www.yiiframework.com/license/
  12 + */
  13 + require( 'Initializer.php' );
  14 + if (!extension_loaded('openssl')) {
  15 + die( 'The OpenSSL PHP extension is required by Yii2.' );
  16 + }
  17 + Initializer::initialize();
... ...