/**
  * Copia recurssivamente os arquivos e diretorios de um array de paths
  *
  * @param array $errors
  * @param bool $copyAll
  * @param array $rollback
  * @param Command $command
  * @param array $paths
  */
 public static function recursiveCopy(array &$errors, &$copyAll, array &$rollback, Command $command, array $paths)
 {
     //loop em todos os diretorios de destino
     foreach ($paths as $key => $value) {
         if (!is_dir($value)) {
             //Se o diretorio não existir
             //Cria o diretorio que não existe
             if (mkdir($value)) {
                 //Cria registro no rollback dizendo uma pasta foi criada
                 $rollback[Strings::ROLLBACK_DIR_CREATED_TAG][] = $value;
             }
         }
     }
     //Loop em todas as pastas
     foreach ($paths as $key => $value) {
         if (empty($errors)) {
             //Se os comandos anteriores rodarem com sucesso
             //Copia lista de arquivos no diretorio para variavel arquivos
             $arquivos = scandir($key);
             //Loop em todos os arquivos do modulo
             for ($i = Constants::FIRST_FILE; $i < count($arquivos); $i++) {
                 if (empty($errors)) {
                     if (!is_dir($key . $arquivos[$i])) {
                         //Se os comandos anteriores rodarem com sucesso e o arquivo não for uma pasta
                         $explodedFileName = explode(Strings::PATH_SEPARATOR, $value . $arquivos[$i]);
                         $filename = $explodedFileName[count($explodedFileName) - 1];
                         //Verifica se o arquivo existe
                         if (!file_exists($value . $arquivos[$i])) {
                             //Cria registro no rollback dizendo que o arquivo foi copiado
                             $rollback[Strings::ROLLBACK_MODULE_ORDINARY_FILE_COPY_TAG][EscapeHelper::encode($value . $arquivos[$i])] = Strings::EMPTY_STRING;
                             //verifica se a copia ocorreu com sucesso
                             if (copy($key . $arquivos[$i], $value . $arquivos[$i]) == false) {
                                 //Printa msg de erro
                                 $errors[] = Strings::ordinaryFileCopyError($value . $arquivos[$i]);
                             }
                         } else {
                             if (strtoupper($filename) != strtoupper(Strings::GIT_KEEP_FILE_NAME)) {
                                 //Caso ja exista um arquivo com o mesmo nome no diretorio de destino
                                 //Inicializa variavel que vai receber resposta do usuario dizendo o que fazer
                                 // com o conflito
                                 $answer = Strings::EMPTY_STRING;
                                 //Enquanto o usuario não devolver uma resposta valida
                                 while ($copyAll != true && $answer != Strings::SHORT_YES && $answer != Strings::SHORT_NO && $answer != Strings::SHORT_ALL && $answer != Strings::SHORT_CANCEL) {
                                     //Faz pergunta para o usuario de como proceder
                                     $answer = $command->ask(Strings::replaceOrdinaryFiles($value . $arquivos[$i]), false);
                                 }
                                 //Se a resposta for sim, ou all
                                 if (strtolower($answer) == Strings::SHORT_YES || strtolower($answer) == Strings::SHORT_ALL || $copyAll == true) {
                                     //se a resposta for all
                                     if (strtolower($answer) == Strings::SHORT_ALL) {
                                         //seta variavel all para true
                                         $copyAll = true;
                                     }
                                     //Faz backup do arquivo que será substituido
                                     $rollback[Strings::ROLLBACK_MODULE_ORDINARY_FILE_COPY_TAG][EscapeHelper::encode($value . $arquivos[$i])] = EscapeHelper::encode(file_get_contents($value . $arquivos[$i]));
                                     //verifica se a substituição ocorreu com sucesso
                                     if (copy($key . $arquivos[$i], $value . $arquivos[$i]) == false) {
                                         //Se houver erro ao copiar arquivo
                                         //Printa msg de erro
                                         $errors[] = Strings::ordinaryFileReplaceError($value . $arquivos[$i]);
                                     }
                                 } else {
                                     if (strtolower($answer) == Strings::SHORT_CANCEL) {
                                         //se a resposta foi cancelar
                                         //Printa msg de erro
                                         $errors[] = Strings::userRequestedAbort();
                                         //break the file loop
                                         break 2;
                                     }
                                 }
                             }
                         }
                     } else {
                         $newPath = [$key . $arquivos[$i] . "/" => $value . $arquivos[$i] . "/"];
                         self::recursiveCopy($errors, $copyAll, $rollback, $command, $newPath);
                     }
                 }
             }
         }
     }
 }
 /**
  * Copia arquivos convencionais do modulo (qualquer coisa exceto migrations) para as respectivas pastas
  *
  * @param string $moduleType
  * @param string $moduleName
  * @param string $copyAll
  * @param array $rollback
  * @param Command $command
  * @param bool $allowReplace
  * @return array|bool
  */
 public static function makeMigrationsCopies($moduleType, $moduleName, &$copyAll, array &$rollback, Command $command, $allowReplace = true)
 {
     $errors = [];
     //Inicia o Rollback de arquivos copiados
     $rollback[Strings::ROLLBACK_MODULE_MIGRATION_FILE_TAG] = array();
     //Inicia o Rollback de arquivos deletados
     $rollback[Strings::ROLLBACK_MODULE_MIGRATION_DELETED_FILE_TAG] = array();
     //Copia lista de arquivos no diretorio de migrations para variavel arquivos
     $arquivos = scandir(PathHelper::getModuleMigrationsPath($moduleType, $moduleName));
     //Loop em todos os arquivos do modulo
     for ($i = Constants::FIRST_FILE; $i < count($arquivos); $i++) {
         //Quebra as palavras  da migration dentro de um array
         $explodedModuleMigrationName = explode(Strings::MIGRATIONS_WORD_SEPARATOR, $arquivos[$i]);
         //Pega remove a parte do nome referente ao timestamp
         $SimplifiedModuleMigrationName = implode(Strings::MIGRATIONS_WORD_SEPARATOR, array_slice($explodedModuleMigrationName, Constants::MIGRATION_FILE_NAME_ARRAY_START));
         //Flag que indica se o arquivo existe
         $migrationPos = false;
         //Pega migrations do projeto
         $migrationFiles = scandir(PathHelper::getLaravelMigrationsPath());
         foreach ($migrationFiles as $migrationIndex => $migrationFile) {
             //Quebra as palavras  da migration dentro de um array
             $explodedMigrationFileName = explode(Strings::MIGRATIONS_WORD_SEPARATOR, $migrationFile);
             //Pega remove a parte do nome referente ao timestamp
             $SimplifiedMigratioFileName = implode(Strings::MIGRATIONS_WORD_SEPARATOR, array_slice($explodedMigrationFileName, Constants::MIGRATION_FILE_NAME_ARRAY_START));
             //Verifica se a migration já existe
             if ($SimplifiedMigratioFileName == $SimplifiedModuleMigrationName) {
                 //marca o arquivo de migration existente migration
                 $migrationPos = $migrationIndex;
                 //quebra o loop
                 break;
             }
         }
         $explodedFileName = explode(Strings::PATH_SEPARATOR, PathHelper::getModuleMigrationsPath($moduleType, $moduleName) . $arquivos[$i]);
         $filename = $explodedFileName[count($explodedFileName) - 1];
         if (strtoupper($filename) != strtoupper(Strings::GIT_KEEP_FILE_NAME)) {
             if ($migrationPos == false) {
                 //Se o arquivo não existir
                 $migrationCounter = Configs::getConfig(PathHelper::getModuleGeneralConfig(), Strings::CONFIG_MIGRATIONS_COUNTER);
                 Configs::setConfig(PathHelper::getModuleGeneralConfig(), Strings::CONFIG_MIGRATIONS_COUNTER, $migrationCounter + 1);
                 if (copy(PathHelper::getModuleMigrationsPath($moduleType, $moduleName) . $arquivos[$i], PathHelper::getLaravelMigrationsPath() . Strings::timestampPadding($migrationCounter) . Strings::MIGRATIONS_WORD_SEPARATOR . $SimplifiedModuleMigrationName) == false) {
                     $errors[] = Strings::migrationsFileCopyError($arquivos[$i]);
                 }
                 //Sinaliza o no arquivo copiado
                 $rollback[Strings::ROLLBACK_MODULE_MIGRATION_FILE_TAG][] = EscapeHelper::encode(PathHelper::getLaravelMigrationsPath() . Strings::timestampPadding($migrationCounter) . Strings::MIGRATIONS_WORD_SEPARATOR . $SimplifiedModuleMigrationName);
             } else {
                 //Se o arquivo ja existir
                 if ($allowReplace) {
                     //Inicializa variavel que vai receber resposta do usuario dizendo o que fazer
                     // com o conflito
                     $answer = Strings::EMPTY_STRING;
                     //Enquanto o usuario não devolver uma resposta valida
                     while ($copyAll != true && $answer != Strings::SHORT_YES && $answer != Strings::SHORT_NO && $answer != Strings::SHORT_ALL && $answer != Strings::SHORT_CANCEL) {
                         //Faz pergunta para o usuario de como proceder
                         $answer = $command->ask(Strings::replaceMigrationFiles($arquivos[$i]), false);
                     }
                     //Se a resposta for sim, ou all
                     if (strtolower($answer) == Strings::SHORT_YES || strtolower($answer) == Strings::SHORT_ALL || $copyAll == true) {
                         //se a resposta for all
                         if (strtolower($answer) == Strings::SHORT_ALL) {
                             //seta variavel all para true
                             $copyAll = true;
                         }
                         //Captura o numero da migration
                         $migrationCounter = Configs::getConfig(PathHelper::getModuleGeneralConfig(), Strings::CONFIG_MIGRATIONS_COUNTER);
                         //Atualiza o contador de migrations
                         Configs::setConfig(PathHelper::getModuleGeneralConfig(), Strings::CONFIG_MIGRATIONS_COUNTER, $migrationCounter + 1);
                         //Sinaliza o no arquivo copiado
                         $rollback[Strings::ROLLBACK_MODULE_MIGRATION_FILE_TAG][] = EscapeHelper::encode(PathHelper::getModuleMigrationsPath($moduleType, $moduleName) . Strings::timestampPadding($migrationCounter) . Strings::MIGRATIONS_WORD_SEPARATOR . $SimplifiedModuleMigrationName);
                         //Faz backup do arquivo que será substituido
                         $rollback[Strings::ROLLBACK_MODULE_MIGRATION_DELETED_FILE_TAG][EscapeHelper::encode(PathHelper::getLaravelMigrationsPath() . $migrationFiles[$migrationPos])] = EscapeHelper::encode(file_get_contents(PathHelper::getLaravelMigrationsPath() . $migrationFiles[$migrationPos]));
                         //Deletar o arquivo antigo
                         if (unlink(PathHelper::getLaravelMigrationsPath() . $migrationFiles[$migrationPos]) == false) {
                             $errors[] = Strings::migrationsFileDeleteError($arquivos[$i]);
                         }
                         //verifica se a substituição ocorreu com sucesso
                         if (copy(PathHelper::getModuleMigrationsPath($moduleType, $moduleName) . $arquivos[$i], Strings::timestampPadding($migrationCounter) . Strings::MIGRATIONS_WORD_SEPARATOR . $SimplifiedModuleMigrationName) == false) {
                             $errors[] = Strings::migrationsFileCopyError($arquivos[$i]);
                         }
                     } else {
                         if (strtolower($answer) == Strings::SHORT_CANCEL) {
                             //se a resposta foi cancelar
                             //Printa msg de erro
                             $errors[] = Strings::userRequestedAbort();
                             //break the file loop
                             break;
                         }
                     }
                 }
             }
         }
     }
     return !empty($errors) ? $errors : true;
 }