<commit_before><?php

/**
 * Operator Handler
 *
 * Copyright 2016-2019 <NAME> <<EMAIL>>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace core\handler;

use core\parser\data;
use core\parser\trustzone;

class operator extends factory
{
    /**
     * Initialize operator
     */
    public static function init(): void
    {
        try {
            //Build initial dependency
            parent::build_dep(self::$init);

            //Run dependency
            foreach (self::$init as $item) {
                self::build_caller(...$item);
            }

            unset($item);
        } catch (\Throwable $throwable) {
            error::exception_handler(new \Exception($throwable->getMessage(), E_USER_ERROR));
            unset($throwable);
        }
    }

    /**
     * Run CGI process
     */
    public static function run_cgi(): void
    {
        //Load list
        $load_list = [];

        //Process orders
        while (!is_null($item_list = array_shift(parent::$cmd_cgi))) {
            //Get name & class
            $class = parent::build_name($name = array_shift($item_list));

            try {
                //Process dependency
                if (false !== strpos($module = strtr($name, '\\', '/'), '/')) {
                    $module = strstr($module, '/', true);
                }

                if (isset(parent::$load[$module]) && !in_array($module, $load_list, true)) {
                    $dep_list = is_string(parent::$load[$module]) ? [parent::$load[$module]] : parent::$load[$module];

                    //Build dependency
                    parent::build_dep($dep_list);

                    //Call dependency
                    foreach ($dep_list as $dep) {
                        self::build_caller(...$dep);
                    }

                    $load_list[] = $module;
                    unset($dep_list, $dep);
                }

                //Check & load class
                if (!class_exists($class, false) && !self::load_class($class)) {
                    //Class NOT exist
                    continue;
                }

                //Check TrustZone permission
                if (empty($tz_list = trustzone::init($class))) {
                    //TrustZone NOT open
                    continue;
                }

                //Get function list & target list
                $func_list   = get_class_methods($class);
                $target_list = !empty($item_list) ? array_intersect($item_list, $tz_list, $func_list) : array_intersect($tz_list, $func_list);

                unset($module, $tz_list, $func_list, $item_list);

                //Process target list
                foreach ($target_list as $target) {
                    //Get TrustZone data
                    $tz_dep = trustzone::get_dep($target);

                    //Build pre/post dependency
                    parent::build_dep($tz_dep['pre']);
                    parent::build_dep($tz_dep['post']);

                    //Call pre dependency
                    foreach ($tz_dep['pre'] as $tz_item) {
                        self::build_caller(...$tz_item);
                    }

                    //Verify TrustZone params
                    trustzone::verify($class, $target);

                    //Build target caller
                    self::build_caller($name, $class, $target);

                    //Call post dependency
                    foreach ($tz_dep['post'] as $tz_item) {
                        self::build_caller(...$tz_item);
                    }
                }
            } catch (\Throwable $throwable) {
                error::exception_handler($throwable);
                unset($throwable);
            }
        }

        unset($load_list, $item_list, $class, $name, $target_list, $target, $tz_dep, $tz_item);
    }

    /**
     * Run CLI process
     */
    public static function run_cli(): void
    {
        //Process orders
        while (!is_null($item_list = array_shift(parent::$cmd_cli))) {
            try {
                //Prepare command
                $command = '"' . $item_list['cmd'] . '"';

                //Append arguments
                if (isset($item_list['argv'])) {
                    $command .= $item_list['argv'];
                }

                //Create process
                $process = proc_open(platform::cmd_proc($command), [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);

                if (!is_resource($process)) {
                    throw new \Exception($item_list['key'] . '=>' . $item_list['cmd'] . ': Access denied or command ERROR!', E_USER_WARNING);
                }

                //Send data via pipe
                if (isset($item_list['pipe'])) {
                    fwrite($pipes[0], $item_list['pipe']);
                }

                //Collect result
                if ($item_list['ret'] && '' !== $data = self::read_pipe([$process, $pipes[1]], $item_list['time'])) {
                    parent::$result[$item_list['key']] = &$data;
                    unset($data);
                }

                //Close pipes (ignore process)
                foreach ($pipes as $pipe) {
                    fclose($pipe);
                }
            } catch (\Throwable $throwable) {
                error::exception_handler($throwable);
                unset($throwable);
            }
        }

        unset($item_list, $command, $process, $pipes, $pipe);
    }

    /**
     * Load class file
     *
     * @param string $class
     *
     * @return bool
     */
    private static function load_class(string $class): bool
    {
        $load = false;
        $file = trim(strtr($class, '\\', DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR) . '.php';
        $list = false !== strpos($file, DIRECTORY_SEPARATOR) ? [ROOT] : parent::$path;

        foreach ($list as $path) {
            if (is_string($path = realpath($path . $file))) {
                //Require script file
                require $path;

                //Check class status
                if ($load = class_exists($class, false)) {
                    break;
                }
            }
        }

        unset($class, $file, $list, $path);
        return $load;
    }

    /**
     * Build mapped key
     *
     * @param string $class
     * @param string $method
     *
     * @return string
     */
    private static function build_key(string $class, string $method): string
    {
        $key = parent::$param_cgi[$class . '-' . $method] ?? (parent::$param_cgi[$class] ?? $class) . '/' . $method;

        unset($class, $method);
        return $key;
    }

    /**
     * Build method caller
     *
     * @param string $order
     * @param string $class
     * @param string $method
     *
     * @throws \ReflectionException
     */
    private static function build_caller(string $order, string $class, string $method): void
    {
        //Get reflection
        $reflect = self::reflect_method($class, $method);

        //Call constructor
        if ('__construct' === $method) {
            parent::obtain($class, data::build_argv($reflect, parent::$data));

            unset($order, $class, $method, $reflect);
            return;
        }

        //Using class object
        if (!$reflect->isStatic()) {
            $class = method_exists($class, '__construct')
                ? parent::obtain($class, data::build_argv(self::reflect_method($class, '__construct'), parent::$data))
                : parent::obtain($class);
        }

        //Call method (with params)
        $result = !empty($params = data::build_argv($reflect, parent::$data))
            ? forward_static_call_array([$class, $method], $params)
            : forward_static_call([$class, $method]);

        //Save result (Try mapping keys)
        if (isset($result)) {
            parent::$result[self::build_key($order, $method)] = &$result;
        }

        unset($order, $class, $method, $reflect, $params, $result);
    }

    /**
     * Reflect method
     * Store constructor
     *
     * @param string $class
     * @param string $method
     *
     * @return \ReflectionMethod
     * @throws \ReflectionException
     */
    private static function reflect_method(string $class, string $method): \ReflectionMethod
    {
        //Reflection list
        static $list = [];

        //Return when exist
        if (isset($list[$class])) {
            return $list[$class];
        }

        //Get method reflection
        $reflect = new \ReflectionMethod($class, $method);

        //Check method visibility
        if (!$reflect->isPublic()) {
            throw new \ReflectionException($class . '::' . $method . ': NOT for public!', E_USER_WARNING);
        }

        //Save constructor reflection
        if ('__construct' === $method) {
            $list[$class] = &$reflect;
        }

        unset($class, $method);
        return $reflect;
    }

    /**
     * Get stream content
     *
     * @param array $process
     * @param int   $timeout
     *
     * @return string
     */
    private static function read_pipe(array $process, int $timeout): string
    {
        $timer  = 0;
        $result = '';

        while (0 === $timeout || $timer <= $timeout) {
            if (proc_get_status($process[0])['running']) {
                usleep(1000);
                $timer += 1000;
            } else {
                $result = trim(stream_get_contents($process[1]));
                break;
            }
        }

        unset($process, $timeout, $timer);
        return $result;
    }
}<commit_msg>Using another way to control LOAD calling logic<commit_after><?php

/**
 * Operator Handler
 *
 * Copyright 2016-2019 <NAME> <<EMAIL>>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace core\handler;

use core\parser\data;
use core\parser\trustzone;

class operator extends factory
{
    /**
     * Initialize operator
     */
    public static function init(): void
    {
        try {
            //Build initial dependency
            parent::build_dep(self::$init);

            //Run dependency
            foreach (self::$init as $item) {
                self::build_caller(...$item);
            }

            unset($item);
        } catch (\Throwable $throwable) {
            error::exception_handler(new \Exception($throwable->getMessage(), E_USER_ERROR));
            unset($throwable);
        }
    }

    /**
     * Run CGI process
     */
    public static function run_cgi(): void
    {
        //Process orders
        while (!is_null($item_list = array_shift(parent::$cmd_cgi))) {
            //Get name & class
            $class = parent::build_name($name = array_shift($item_list));

            try {
                //Process dependency
                if (false !== strpos($module = strtr($name, '\\', '/'), '/')) {
                    $module = strstr($module, '/', true);
                }

                if (isset(parent::$load[$module])) {
                    $dep_list = is_string(parent::$load[$module]) ? [parent::$load[$module]] : parent::$load[$module];

                    //Build dependency
                    parent::build_dep($dep_list);

                    //Call dependency
                    foreach ($dep_list as $dep) {
                        self::build_caller(...$dep);
                    }

                    unset(parent::$load[$module], $dep_list, $dep);
                }

                //Check & load class
                if (!class_exists($class, false) && !self::load_class($class)) {
                    //Class NOT exist
                    continue;
                }

                //Check TrustZone permission
                if (empty($tz_list = trustzone::init($class))) {
                    //TrustZone NOT open
                    continue;
                }

                //Get function list & target list
                $func_list   = get_class_methods($class);
                $target_list = !empty($item_list) ? array_intersect($item_list, $tz_list, $func_list) : array_intersect($tz_list, $func_list);

                unset($module, $tz_list, $func_list, $item_list);

                //Process target list
                foreach ($target_list as $target) {
                    //Get TrustZone data
                    $tz_dep = trustzone::get_dep($target);

                    //Build pre/post dependency
                    parent::build_dep($tz_dep['pre']);
                    parent::build_dep($tz_dep['post']);

                    //Call pre dependency
                    foreach ($tz_dep['pre'] as $tz_item) {
                        self::build_caller(...$tz_item);
                    }

                    //Verify TrustZone params
                    trustzone::verify($class, $target);

                    //Build target caller
                    self::build_caller($name, $class, $target);

                    //Call post dependency
                    foreach ($tz_dep['post'] as $tz_item) {
                        self::build_caller(...$tz_item);
                    }
                }
            } catch (\Throwable $throwable) {
                error::exception_handler($throwable);
                unset($throwable);
            }
        }

        unset($item_list, $class, $name, $target_list, $target, $tz_dep, $tz_item);
    }

    /**
     * Run CLI process
     */
    public static function run_cli(): void
    {
        //Process orders
        while (!is_null($item_list = array_shift(parent::$cmd_cli))) {
            try {
                //Prepare command
                $command = '"' . $item_list['cmd'] . '"';

                //Append arguments
                if (isset($item_list['argv'])) {
                    $command .= $item_list['argv'];
                }

                //Create process
                $process = proc_open(platform::cmd_proc($command), [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes);

                if (!is_resource($process)) {
                    throw new \Exception($item_list['key'] . '=>' . $item_list['cmd'] . ': Access denied or command ERROR!', E_USER_WARNING);
                }

                //Send data via pipe
                if (isset($item_list['pipe'])) {
                    fwrite($pipes[0], $item_list['pipe']);
                }

                //Collect result
                if ($item_list['ret'] && '' !== $data = self::read_pipe([$process, $pipes[1]], $item_list['time'])) {
                    parent::$result[$item_list['key']] = &$data;
                    unset($data);
                }

                //Close pipes (ignore process)
                foreach ($pipes as $pipe) {
                    fclose($pipe);
                }
            } catch (\Throwable $throwable) {
                error::exception_handler($throwable);
                unset($throwable);
            }
        }

        unset($item_list, $command, $process, $pipes, $pipe);
    }

    /**
     * Load class file
     *
     * @param string $class
     *
     * @return bool
     */
    private static function load_class(string $class): bool
    {
        $load = false;
        $file = trim(strtr($class, '\\', DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR) . '.php';
        $list = false !== strpos($file, DIRECTORY_SEPARATOR) ? [ROOT] : parent::$path;

        foreach ($list as $path) {
            if (is_string($path = realpath($path . $file))) {
                //Require script file
                require $path;

                //Check class status
                if ($load = class_exists($class, false)) {
                    break;
                }
            }
        }

        unset($class, $file, $list, $path);
        return $load;
    }

    /**
     * Build mapped key
     *
     * @param string $class
     * @param string $method
     *
     * @return string
     */
    private static function build_key(string $class, string $method): string
    {
        $key = parent::$param_cgi[$class . '-' . $method] ?? (parent::$param_cgi[$class] ?? $class) . '/' . $method;

        unset($class, $method);
        return $key;
    }

    /**
     * Build method caller
     *
     * @param string $order
     * @param string $class
     * @param string $method
     *
     * @throws \ReflectionException
     */
    private static function build_caller(string $order, string $class, string $method): void
    {
        //Get reflection
        $reflect = self::reflect_method($class, $method);

        //Call constructor
        if ('__construct' === $method) {
            parent::obtain($class, data::build_argv($reflect, parent::$data));

            unset($order, $class, $method, $reflect);
            return;
        }

        //Using class object
        if (!$reflect->isStatic()) {
            $class = method_exists($class, '__construct')
                ? parent::obtain($class, data::build_argv(self::reflect_method($class, '__construct'), parent::$data))
                : parent::obtain($class);
        }

        //Call method (with params)
        $result = !empty($params = data::build_argv($reflect, parent::$data))
            ? forward_static_call_array([$class, $method], $params)
            : forward_static_call([$class, $method]);

        //Save result (Try mapping keys)
        if (isset($result)) {
            parent::$result[self::build_key($order, $method)] = &$result;
        }

        unset($order, $class, $method, $reflect, $params, $result);
    }

    /**
     * Reflect method
     * Store constructor
     *
     * @param string $class
     * @param string $method
     *
     * @return \ReflectionMethod
     * @throws \ReflectionException
     */
    private static function reflect_method(string $class, string $method): \ReflectionMethod
    {
        //Reflection list
        static $list = [];

        //Return when exist
        if (isset($list[$class])) {
            return $list[$class];
        }

        //Get method reflection
        $reflect = new \ReflectionMethod($class, $method);

        //Check method visibility
        if (!$reflect->isPublic()) {
            throw new \ReflectionException($class . '::' . $method . ': NOT for public!', E_USER_WARNING);
        }

        //Save constructor reflection
        if ('__construct' === $method) {
            $list[$class] = &$reflect;
        }

        unset($class, $method);
        return $reflect;
    }

    /**
     * Get stream content
     *
     * @param array $process
     * @param int   $timeout
     *
     * @return string
     */
    private static function read_pipe(array $process, int $timeout): string
    {
        $timer  = 0;
        $result = '';

        while (0 === $timeout || $timer <= $timeout) {
            if (proc_get_status($process[0])['running']) {
                usleep(1000);
                $timer += 1000;
            } else {
                $result = trim(stream_get_contents($process[1]));
                break;
            }
        }

        unset($process, $timeout, $timer);
        return $result;
    }
}
{'fraction_non_alphanumeric': 0.13773021403683425, 'fraction_numerical': 0.002588352414136386, 'mean_word_length': 1.5893800747519011, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3068492', 'n_tokens_mistral': 5508, 'n_tokens_neox': 5233, 'n_words': 1261}