<commit_before><?php declare(strict_types=1);

namespace Smr\Container;

use DI\Container;
use DI\ContainerBuilder;
use Dotenv\Dotenv;
use mysqli;
use Smr\Database;
use Smr\DatabaseProperties;
use Smr\Epoch;
use Smr\Session;
use Smr\Template;
use function DI\autowire;

/**
 * A wrapper around the DI\Container functionality that will allow
 * static usage of container methods.
 */
class DiContainer {
	private static DiContainer $instance;
	private Container $container;

	private function __construct(bool $enableCompilation) {
		$this->container = $this->buildContainer($enableCompilation);
	}

	private function getDefinitions() : array {
		return [
			/*
			 * mysqli is a 3rd party library, and we do not have control over its constructor.
			 * In order for PHP-DI to construct an instance of a class, each constructor argument must
			 * be able to be constructed.
			 * PHP-DI cannot construct mysqli by itself, because all of its arguments are primitive types.
			 * Therefore, we need to declare a provider factory for the container to use when constructing new instances.
			 *
			 * The factories themselves are able to use dependency injection as well, so we can provide the DatabaseProperties
			 * typehint to make sure the container constructs an instance and provides it to the factory.
			 */
			mysqli::class => function(DatabaseProperties $dbProperties): mysqli {
				return Database::mysqliFactory($dbProperties);
			},
			Dotenv::class => function(): Dotenv {
				return Dotenv::createArrayBacked(CONFIG, 'env');
			},
			'DatabaseName' => function(DatabaseProperties $dbProperties): string {
				return $dbProperties->getDatabaseName();
			},
			// Explicitly name all classes that are autowired, so we can take advantage of
			// the compiled container feature for a performance boost
			Epoch::class => autowire(),
			DatabaseProperties::class => autowire(),
			Database::class => autowire()
				->constructorParameter('dbName', \DI\get('DatabaseName')),
			Session::class => autowire(),
			Template::class => autowire(),
		];
	}

	private function buildContainer(bool $enableCompilation) : Container {
		$builder = new ContainerBuilder();
		$builder
			->addDefinitions($this->getDefinitions())
			->useAnnotations(false)
			->useAutowiring(true);
		if ($enableCompilation) {
			// The CompiledContainer.php will be saved to the /tmp directory on the Docker container once
			// during its lifecycle (first request)
			$builder->enableCompilation("/tmp");
		}
		return $builder->build();<commit_msg>Ignore deprecation warnings from PHP-DI in PHP 8.1<commit_after><?php declare(strict_types=1);

namespace Smr\Container;

use DI\Container;
use DI\ContainerBuilder;
use Dotenv\Dotenv;
use mysqli;
use Smr\Database;
use Smr\DatabaseProperties;
use Smr\Epoch;
use Smr\Session;
use Smr\Template;
use function DI\autowire;

/**
 * A wrapper around the DI\Container functionality that will allow
 * static usage of container methods.
 */
class DiContainer {
	private static DiContainer $instance;
	private Container $container;

	private function __construct(bool $enableCompilation) {
		$this->container = $this->buildContainer($enableCompilation);
	}

	private function getDefinitions() : array {
		return [
			/*
			 * mysqli is a 3rd party library, and we do not have control over its constructor.
			 * In order for PHP-DI to construct an instance of a class, each constructor argument must
			 * be able to be constructed.
			 * PHP-DI cannot construct mysqli by itself, because all of its arguments are primitive types.
			 * Therefore, we need to declare a provider factory for the container to use when constructing new instances.
			 *
			 * The factories themselves are able to use dependency injection as well, so we can provide the DatabaseProperties
			 * typehint to make sure the container constructs an instance and provides it to the factory.
			 */
			mysqli::class => function(DatabaseProperties $dbProperties): mysqli {
				return Database::mysqliFactory($dbProperties);
			},
			Dotenv::class => function(): Dotenv {
				return Dotenv::createArrayBacked(CONFIG, 'env');
			},
			'DatabaseName' => function(DatabaseProperties $dbProperties): string {
				return $dbProperties->getDatabaseName();
			},
			// Explicitly name all classes that are autowired, so we can take advantage of
			// the compiled container feature for a performance boost
			Epoch::class => autowire(),
			DatabaseProperties::class => autowire(),
			Database::class => autowire()
				->constructorParameter('dbName', \DI\get('DatabaseName')),
			Session::class => autowire(),
			Template::class => autowire(),
		];
	}

	private function buildContainer(bool $enableCompilation) : Container {
		$builder = new ContainerBuilder();
		$builder
			->addDefinitions($this->getDefinitions())
			->useAnnotations(false)
			->useAutowiring(true);
		if ($enableCompilation) {
			// The CompiledContainer.php will be saved to the /tmp directory on the Docker container once
			// during its lifecycle (first request)
			$builder->enableCompilation("/tmp");
		}
		// TODO: deprecation warnings suppressed until PHP 8.1 supported!
		// See https://github.com/PHP-DI/PHP-DI/pull/794.
		return @$builder->build();
{'fraction_non_alphanumeric': 0.10149654643131235, 'fraction_numerical': 0.002110514198004605, 'mean_word_length': 4.218218218218218, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 39, 'https://': 1, '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': '4316853', 'n_tokens_mistral': 1587, 'n_tokens_neox': 1371, 'n_words': 506}