<commit_before><?php

namespace drunomics\Phapp;

use drunomics\Phapp\Exception\PhappEnvironmentUndefinedException;
use drunomics\Phapp\Exception\PhappManifestMalformedException;
use drunomics\Phapp\Task\Exec;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Robo\Tasks;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;

/**
 * Base class for phapp command classes.
 */
abstract class PhappCommandBase extends Tasks implements LoggerAwareInterface {

  use LoggerAwareTrait;

  /**
   * Whether the command requires a valid phapp manifest.
   *
   * @var bool
   */
  protected $requiresPhappManifest = TRUE;

  /**
   * The maniftest of the current phapp instance.
   *
   * @var \drunomics\Phapp\PhappManifest|null
   */
  protected $phappManifest;

  /**
   * The global phapp config.
   *
   * @var \drunomics\Phapp\GlobalConfig
   */
  protected $globalConfig;

  /**
   * Ensures with a valid phapp definition to interact with.
   *
   * @hook validate
   */
  public function init() {
    $this->globalConfig = GlobalConfig::discoverConfig();
    if ($this->requiresPhappManifest) {
      $this->phappManifest = PhappManifest::getInstance();
      $this->initShellEnvironment();
    }
    $this->stopOnFail(TRUE);
  }

  /**
   * Initializes the shell environment.
   *
   * Switches the working directory, initializes all phapp environment variables
   * and adds the composer bin-dir to the path.
   *
   * @return $this
   */
  protected function initShellEnvironment() {
    // Switch working directory.
    chdir($this->phappManifest->getFile()->getPath());
    // Add the composer bin-dir to the path.
    $path = getenv("PATH");
    putenv("PATH=../vendor/bin/:../bin:$path");
    return $this;
  }

  /**
   * Gets dotenv variables from the given directory.
   *
   * @param string $directory
   *   (optional) The director
   * @param \drunomics\Phapp\PhappManifest $manifest
   *   (optional) Manifest
   *
   * @return string[]
   *   The array of environment variables, keyed variable name.
   *
   * @throws \drunomics\Phapp\Exception\PhappEnvironmentUndefinedException
   *   Thrown when the environment is undefined.
   */
  protected function getPhappEnviromentVariables($directory = './', $manifest = NULL) {
    // Normalize directory paths to ahve a trailing slash.
    $directory = rtrim($directory, '/');

    // Abstract function to sort the search result alphabetically by filename.
    $sort = function (\SplFileInfo $first, \SplFileInfo $second) {
      return $first->getBasename() < $second->getBasename() ? -1 : 1;
    };

    $finder = new Finder();
    $finder->files()
      ->name('.env')
      ->name('.*.env')
      ->ignoreDotFiles(FALSE)
      ->in($directory)
      ->depth('== 0')
      ->sort($sort);

    $env_vars = [];
    // Try to extract env variables from given manifest.
    // Fallback to the root manifest if no other is provided.
    if ($manifest || $manifest = $this->phappManifest) {
      $env_vars = array_replace($env_vars, $manifest->getEnvironment());
    }
    // Exit, if no dotenv files found and no env variables provided in manifest.
    if ($finder->count() == 0 && !$env_vars) {
      return $env_vars;
    }

    // Extract env vars from dotenv files.
    foreach ($finder as $file) {
      // Add dotenv vars.
      $dotenv = new Dotenv();
      $env_vars = array_replace($env_vars, $dotenv->parse(file_get_contents($file->getPathname()), $file->getPathname()));
    }

    // Ensure the PHAPP_ENV variable will be set.
    if (!getenv('PHAPP_ENV') && empty($env_vars['PHAPP_ENV'])) {
      throw new PhappEnvironmentUndefinedException();
    }
    return $env_vars;
  }

  /**
   * Silently execute a command in bash.
   *
   * @param string $command
   *   The command.
   *<commit_msg>ISSUE-18 Populate already parsed vars so they are accessible for next parsings.<commit_after><?php

namespace drunomics\Phapp;

use drunomics\Phapp\Exception\PhappEnvironmentUndefinedException;
use drunomics\Phapp\Exception\PhappManifestMalformedException;
use drunomics\Phapp\Task\Exec;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Robo\Tasks;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;

/**
 * Base class for phapp command classes.
 */
abstract class PhappCommandBase extends Tasks implements LoggerAwareInterface {

  use LoggerAwareTrait;

  /**
   * Whether the command requires a valid phapp manifest.
   *
   * @var bool
   */
  protected $requiresPhappManifest = TRUE;

  /**
   * The maniftest of the current phapp instance.
   *
   * @var \drunomics\Phapp\PhappManifest|null
   */
  protected $phappManifest;

  /**
   * The global phapp config.
   *
   * @var \drunomics\Phapp\GlobalConfig
   */
  protected $globalConfig;

  /**
   * Ensures with a valid phapp definition to interact with.
   *
   * @hook validate
   */
  public function init() {
    $this->globalConfig = GlobalConfig::discoverConfig();
    if ($this->requiresPhappManifest) {
      $this->phappManifest = PhappManifest::getInstance();
      $this->initShellEnvironment();
    }
    $this->stopOnFail(TRUE);
  }

  /**
   * Initializes the shell environment.
   *
   * Switches the working directory, initializes all phapp environment variables
   * and adds the composer bin-dir to the path.
   *
   * @return $this
   */
  protected function initShellEnvironment() {
    // Switch working directory.
    chdir($this->phappManifest->getFile()->getPath());
    // Add the composer bin-dir to the path.
    $path = getenv("PATH");
    putenv("PATH=../vendor/bin/:../bin:$path");
    return $this;
  }

  /**
   * Gets dotenv variables from the given directory.
   *
   * @param string $directory
   *   (optional) The director
   * @param \drunomics\Phapp\PhappManifest $manifest
   *   (optional) Manifest
   *
   * @return string[]
   *   The array of environment variables, keyed variable name.
   *
   * @throws \drunomics\Phapp\Exception\PhappEnvironmentUndefinedException
   *   Thrown when the environment is undefined.
   */
  protected function getPhappEnviromentVariables($directory = './', $manifest = NULL) {
    // Normalize directory paths to ahve a trailing slash.
    $directory = rtrim($directory, '/');

    // Abstract function to sort the search result alphabetically by filename.
    $sort = function (\SplFileInfo $first, \SplFileInfo $second) {
      return $first->getBasename() < $second->getBasename() ? -1 : 1;
    };

    $finder = new Finder();
    $finder->files()
      ->name('.env')
      ->name('.*.env')
      ->ignoreDotFiles(FALSE)
      ->in($directory)
      ->depth('== 0')
      ->sort($sort);

    $env_vars = [];
    // Try to extract env variables from given manifest.
    // Fallback to the root manifest if no other is provided.
    if ($manifest || $manifest = $this->phappManifest) {
      $env_vars = array_replace($env_vars, $manifest->getEnvironment());
    }
    // Exit, if no dotenv files found and no env variables provided in manifest.
    if ($finder->count() == 0 && !$env_vars) {
      return $env_vars;
    }

    // Extract env vars from dotenv files.
    foreach ($finder as $file) {
      // Add dotenv vars.
      $dotenv = new Dotenv();
      // Parse dotenv vars.
      $parsed_env_vars = $dotenv->parse(file_get_contents($file->getPathname()), $file->getPathname());
      // Populate them to make sure all of them are available for next parsing.
      $dotenv->populate($parsed_env_vars);
      $env_vars = array_replace($env_vars, $parsed_env_vars);
    }

    // Ensure the PHAPP_ENV variable will be set.
    if (!getenv('PHAPP_ENV') && empty($env_vars['PHAPP_ENV'])) {
      throw new PhappEnvironmentUndefinedException();
    }
    return $env_vars;
  }

  /**
   * Silently execute a command in bash.
   *
   * @param string $command
   *   The command.
   *
{'fraction_non_alphanumeric': 0.1261635220125786, 'fraction_numerical': 0.0012578616352201257, 'mean_word_length': 3.0504330106979114, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1746850', 'n_tokens_mistral': 2464, 'n_tokens_neox': 2416, 'n_words': 642}