<commit_before><?php

/*!
 * This file is part of {@link https://github.com/MovLib MovLib}.
 *
 * Copyright © 2013-present {@link https://movlib.org/ MovLib}.
 *
 * MovLib is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
 * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * MovLib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with MovLib.
 * If not, see {@link http://www.gnu.org/licenses/ gnu.org/licenses}.
 */
namespace MovLib\Console\Command\Dev;

use \MovLib\Data\Shell;
use \MovLib\Data\User\FullUser;
use \Symfony\Component\Console\Input\InputArgument;
use \Symfony\Component\Console\Input\InputInterface;
use \Symfony\Component\Console\Output\OutputInterface;

/**
 * Command to create random user(s).
 *
 * @author <NAME> <<EMAIL>>
 * @copyright © 2013 MovLib
 * @license http://www.gnu.org/licenses/agpl.html AGPL-3.0
 * @link https://movlib.org/
 * @since 0.0.1-dev
 */
class RandomUser extends \MovLib\Console\Command\AbstractCommand {


  // ------------------------------------------------------------------------------------------------------------------- Constants


  /**
   * The default amount of random users to generate.
   *
   * @var integer
   */
  const DEFAULT_AMOUNT = 100;


  // ------------------------------------------------------------------------------------------------------------------- Properties


  /**
   * The actual amount of users to generate.
   *
   * @var integer
   */
  protected $amount = self::DEFAULT_AMOUNT;

  /**
   * All characters that are available for the random username generator.
   *
   * We have 62 characters in this array and it was generated with the following code:
   * <pre>array_merge(range("A", "Z"), range("a", "z"), range("0", "9"))</pre>
   *
   * @see RandomUser::getRandomUsername()
   * @todo Should we include some unicode as well?
   * @var string
   */
  protected $characters = [
    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  ];

  /**
   * The <var>RandomUser::$characters</var> count minus one, or in code: <code>count($this->characters) - 1</code>.
   *
   * @see RandomUser::getRandomUsername()
   * @var integer
   */
  protected $charactersCount = 61;

  /**
   * Numeric array containing <b>all</b> usernames, we need this to make sure that we don't generate a username that's
   * already in use.
   *
   * @var array
   */
  protected $usernames = [];


  // ------------------------------------------------------------------------------------------------------------------- Methods


  /**
   * @inheritdoc
   */
  public function configure() {
    $this->setName("create-random-users");
    $this->setDescription("Create one or more random users.");
    $this->addArgument(
      "amount",
      InputArgument::OPTIONAL,
      "The amount of random users to create, defaults to " . self::DEFAULT_AMOUNT . ".",
      self::DEFAULT_AMOUNT
    );
  }

  /**
   * Get a randomly generated username.
   *
   * @return string
   *   The randomly generated username.
   */
  protected function getRandomUsername() {
    $username = null;

    do {
      // 1 to NAME_MAXIMUM_LENGTH, all variations are valid!
      $length   = mt_rand(1, FullUser::NAME_MAXIMUM_LENGTH);
      for ($i = 0; $i < $length; ++$i) {
        $username .= $this->characters[mt_rand(0, $this->charactersCount)];
      }
    }
    // If this username is already in use generate another one.
    while (in_array($username, $this->username));

    $this->usernames[] = $username;
    return $username;
  }

  /**
   * @inheritdoc
   * @global \MovLib\Tool\Database $db
   * @global \MovLib\Data\I18n $i18n
   * @global \MovLib\Tool\Kernel $kernel
   */
  protected function execute(InputInterface $input, OutputInterface $output) {
    global $db, $i18n, $kernel;
    $this->amount = (integer) $input->getArgument("amount");

    $this->write("Preparing to generate <comment>{$this->amount}</comment> random users ...");
    $this->setUsernames();
    $values          = $params          = $usersWithAvatar = null;
    $this->progress->start($this->output, $this->amount);
    $user            = new FullUser();
    $min             = strtotime("-1 year");
    $max             = time();

    $this->write("Creating <comment>{$this->amount}</comment> random users ...");
    for ($i = 0; $i < $this->amount; ++$i) {
      $created = mt_rand($min, $max);
      $name    = $this->getRandomUsername();
      $values .= "(FROM_UNIXTIME(?), ?, FROM_UNIXTIME(?), '', ?, ?, ?, '{$i18n->defaultLanguageCode}'),";
      if ($i % 6 !== 0) {
        $params[]          = $created;
        $params[]          = "jpg";
        $usersWithAvatar[] = $name;
      }
      else {
        $params[] = $params[] = null;
      }
      $params[] = $created;
      $params[] = "{$name}@{$kernel->domainDefault}";
      $params[] = $name;
      $params[] = $this->invoke($user, "passwordHash", [ $name ]);
      $this->progress->advance();
    }
    $values = rtrim($values, ",");
    $this->progress->finish();

    $this->write("Inserting <comment>{$this->amount}</comment> random users into database ...");
    $db->query(
      "INSERT INTO `users` (
        `avatar_changed`,
        `avatar_extension`,
        `created`,
        `dyn_profile`,
        `email`,
        `name`,
        `password`,
        `system_language_code`
      ) VALUES {$values}",
      str_repeat("s", count($params)),
      $params
    );

    if (($c = count($usersWithAvatar))) {
      $this->write("Generating avatar images (every 6th user has none) ...");
      $dim = FullUser::STYLE_SPAN_02;
      $tmp = ini_get("upload_tmp_dir") . "/movdev-command-create-users.jpg";
      Shell::execute("convert -size {$dim}x{$dim} xc: +noise Random {$tmp}");
      $this->setProperty($user, "imageExtension", "jpg");
      $this->progress->start($this->output, $c);
      $in = rtrim(str_repeat("?,", $c), ",");
      $result = $db->query("SELECT `user_id`, `name` FROM `users` WHERE `name` IN ({$in})", str_repeat("s", $c), $usersWithAvatar)->get_result();
      while ($row = $result->fetch_assoc()) {
        $this->setProperty($user, "imageName", $row["name"]);
        $this->invoke($user, "convertImage", [ $tmp, FullUser::STYLE_SPAN_02 ]);
        $this->invoke($user, "convertImage", [ $tmp, FullUser::STYLE_SPAN_01 ]);
        $this->progress->advance();
      }
      unlink($tmp);
      $this->progress->finish();
    }

    $this->write("Successfully created {$this->amount} of random users!", self::MESSAGE_TYPE_INFO);<commit_msg>Fixed random user script<commit_after><?php

/*!
 * This file is part of {@link https://github.com/MovLib MovLib}.
 *
 * Copyright © 2013-present {@link https://movlib.org/ MovLib}.
 *
 * MovLib is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
 * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * MovLib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with MovLib.
 * If not, see {@link http://www.gnu.org/licenses/ gnu.org/licenses}.
 */
namespace MovLib\Console\Command\Dev;

use \MovLib\Data\User\FullUser;
use \Symfony\Component\Console\Input\InputArgument;
use \Symfony\Component\Console\Input\InputInterface;
use \Symfony\Component\Console\Output\OutputInterface;

/**
 * Command to create random user(s).
 *
 * @author <NAME> <<EMAIL>>
 * @copyright © 2013 MovLib
 * @license http://www.gnu.org/licenses/agpl.html AGPL-3.0
 * @link https://movlib.org/
 * @since 0.0.1-dev
 */
class RandomUser extends \MovLib\Console\Command\AbstractCommand {


  // ------------------------------------------------------------------------------------------------------------------- Constants


  /**
   * The default amount of random users to generate.
   *
   * @var integer
   */
  const DEFAULT_AMOUNT = 100;


  // ------------------------------------------------------------------------------------------------------------------- Properties


  /**
   * The actual amount of users to generate.
   *
   * @var integer
   */
  protected $amount = self::DEFAULT_AMOUNT;

  /**
   * All characters that are available for the random username generator.
   *
   * We have 62 characters in this array and it was generated with the following code:
   * <pre>array_merge(range("A", "Z"), range("a", "z"), range("0", "9"))</pre>
   *
   * @see RandomUser::getRandomUsername()
   * @todo Should we include some unicode as well?
   * @var string
   */
  protected $characters = [
    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  ];

  /**
   * The <var>RandomUser::$characters</var> count minus one, or in code: <code>count($this->characters) - 1</code>.
   *
   * @see RandomUser::getRandomUsername()
   * @var integer
   */
  protected $charactersCount = 61;

  /**
   * Numeric array containing <b>all</b> usernames, we need this to make sure that we don't generate a username that's
   * already in use.
   *
   * @var array
   */
  protected $usernames = [];


  // ------------------------------------------------------------------------------------------------------------------- Methods


  /**
   * @inheritdoc
   */
  public function configure() {
    $this->setName("create-random-users");
    $this->setDescription("Create one or more random users.");
    $this->addArgument(
      "amount",
      InputArgument::OPTIONAL,
      "The amount of random users to create, defaults to " . self::DEFAULT_AMOUNT . ".",
      self::DEFAULT_AMOUNT
    );
  }

  /**
   * Get a randomly generated username.
   *
   * @return string
   *   The randomly generated username.
   */
  protected function getRandomUsername() {
    $username = null;

    do {
      // 1 to NAME_MAXIMUM_LENGTH, all variations are valid!
      $length   = mt_rand(1, FullUser::NAME_MAXIMUM_LENGTH);
      for ($i = 0; $i < $length; ++$i) {
        $username .= $this->characters[mt_rand(0, $this->charactersCount)];
      }
    }
    // If this username is already in use generate another one.
    while (in_array($username, $this->usernames));

    $this->usernames[] = $username;
    return $username;
  }

  /**
   * {@inheritdoc}
   * @global \MovLib\Core\Config $config
   * @global \MovLib\Core\Database $db
   * @global \MovLib\Core\FileSystem $fs
   * @global \MovLib\Core\I18n $i18n
   */
  protected function execute(InputInterface $input, OutputInterface $output) {
    global $config, $db, $fs, $i18n;
    $this->amount = (integer) $input->getArgument("amount");

    $this->write("Preparing to generate <comment>{$this->amount}</comment> random users ...");
    $this->setUsernames();
    $values          = $params          = $usersWithAvatar = null;
    $this->progressStart($this->amount);
    $user            = new FullUser();
    $min             = strtotime("-1 year");
    $max             = time();

    $this->write("Creating <comment>{$this->amount}</comment> random users ...");
    for ($i = 0; $i < $this->amount; ++$i) {
      $created = mt_rand($min, $max);
      $name    = $this->getRandomUsername();
      $values .= "(FROM_UNIXTIME(?), ?, FROM_UNIXTIME(?), '', ?, ?, ?, '{$i18n->defaultLanguageCode}'),";
      if ($i % 6 !== 0) {
        $params[]          = $created;
        $params[]          = "jpg";
        $usersWithAvatar[] = $name;
      }
      else {
        $params[] = $params[] = null;
      }
      $params[] = $created;
      $params[] = "{$name}@{$config->hostname}";
      $params[] = $name;
      $params[] = $user->hashPassword($name);
      $this->progressAdvance();
    }
    $values = rtrim($values, ",");
    $this->progressFinish();

    $this->write("Inserting <comment>{$this->amount}</comment> random users into database ...");
    $db->query(
      "INSERT INTO `users` (
        `image_changed`,
        `image_extension`,
        `created`,
        `dyn_about_me`,
        `email`,
        `name`,
        `password`,
        `system_language_code`
      ) VALUES {$values}",
      str_repeat("s", count($params)),
      $params
    );

    if (($c = count($usersWithAvatar))) {
      $this->write("Generating avatar images (every 6th user has none) ...");
      $dim = FullUser::STYLE_SPAN_02;
      $tmp = ini_get("upload_tmp_dir") . "/movdev-command-create-users.jpg";
      $this->exec("convert -size {$dim}x{$dim} xc: +noise Random {$tmp}");
      $ext = new \ReflectionProperty($user, "extension");
      $ext->setAccessible(true);
      $ext->setValue($user, "jpg");
      $this->progressStart($c);
      $in = rtrim(str_repeat("?,", $c), ",");
      $result = $db->query("SELECT `id`, `name` FROM `users` WHERE `name` IN ({$in})", str_repeat("s", $c), $usersWithAvatar)->get_result();
      while ($row = $result->fetch_assoc()) {
        $user->filename = $fs->sanitizeFilename($row["name"]);
        $convert = new \ReflectionMethod($user, "convert");
        $convert->setAccessible(true);
        $convert->invoke($user, $tmp, FullUser::STYLE_SPAN_02);
        $convert->invoke($user, $tmp, FullUser::STYLE_SPAN_01);
        $this->progressAdvance();
      }
      unlink($tmp);
      $this->progressFinish();
    }

    $this->write("Successfully created {$this->amount} of random users!", self::MESSAGE_TYPE_INFO);
{'fraction_non_alphanumeric': 0.2228245760355852, 'fraction_numerical': 0.0079232693911593, 'mean_word_length': 2.430035756853397, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 129, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3129085', 'n_tokens_mistral': 4589, 'n_tokens_neox': 4425, 'n_words': 1182}