<commit_before><?php
namespace Poirot\Stream\Context;

use Poirot\Core;
use Poirot\Core\AbstractOptions;
use Poirot\Core\Interfaces\iOptionImplement;
use Poirot\Core\Interfaces\iPoirotOptions;
use Poirot\Core\Interfaces\iOptionsProvider;
use Poirot\Core\OpenOptions;
use Poirot\Stream\Interfaces\Context\iSContext;

!defined('POIROT_CORE_LOADED') and include_once 'Core.php';

/**
 * TODO contexts
 */
abstract class AbstractContext extends OpenOptions
    implements
    iSContext,
    iOptionsProvider
{
    protected $wrapper = null;

    // params

    /**
     * @var callable
     */
    protected $notification;

    // options

    /**
     * @var iOptionImplement
     */
    protected $options;

    /**
     * @var array[AbstractContext]
     */
    protected $bindContexts = [];

    /**
     * Construct
     *
     * @param array|iPoirotOptions $options Options
     */
    function __construct($options = null)
    {
        $this->__before_construct();

        parent::__construct($options);
    }

    /**
     * Called by __construct
     */
    protected function __before_construct()
    {

    }

    /**
     * Used To Create Context, as php on creating streams
     * contexts get options as associative array with
     * $arr['wrapper']['option'] = $value format
     *
     * @throws \Exception
     * @return string
     */
    function wrapperName()
    {
        $wrapper = $this->wrapper;
        if ($wrapper === null)
            throw new \Exception('No Wrapper Defined Yet!!');

        return $wrapper;
    }

    /**
     * Bind Another Context Along this
     *
     * [
     * * 'socket' => [
            'bindto' => '192.168.0.100:7000',
        ],
     * * 'http' => [
     *      ...
     *  ]
     * ]
     *
     * @param iSContext|array|resource $context
     *
     * @return $this
     */
    function bindWith($context)
    {
        if (is_array($context))
            $context = stream_context_create($context);

        if (is_resource($context) && get_resource_type($context) == 'stream-context')
            $context = new BaseContext($context);

        if (!$context instanceof iSContext)
            // Invalid parameter
            throw new \InvalidArgumentException(
                "Expecting either a stream context resource or array, got " . gettype($context)
            );


        $this->bindContexts[strtolower($context->wrapperName())] = $context;
        return $this;
    }

    /**
     * Context with specific wrapper has bind?
     *
     * @param string $wrapperName
     *
     * @return false|iSContext
     */
    function hasBind($wrapperName)
    {
        return array_key_exists(strtolower($wrapperName), $this->bindContexts);
    }

    /**
     * List of Wrapper Name Of Currently Bind Contexts
     *
     * @return array[ (string) wrapperName ]
     */
    function listBindContexts()
    {
        return array_keys($this->bindContexts);
    }

    // Params:

    /**
     * Set callback function for the notification context parameter
     * @link http://php.net/manual/en/function.stream-notification-callback.php
     *
     * @param callable $notification
     *
     * @return $this
     */
    public function setNotification($notification)
    {
        if (!is_callable($notification))
            throw new \InvalidArgumentException('Notification handler must be a callable.');

        $this->notification = $notification;

        return $this;
    }

    /**
     * @return callable
     */
    public function getNotification()
    {
        return $this->notification;
    }

    // Context:

    /**
     * Set/Retrieves specific options
     *
     * @return OpenOptions<commit_msg>code cleanup<commit_after><?php
namespace Poirot\Stream\Context;

use Poirot\Core;
use Poirot\Core\AbstractOptions;
use Poirot\Core\Interfaces\iOptionImplement;
use Poirot\Core\Interfaces\iPoirotOptions;
use Poirot\Core\Interfaces\iOptionsProvider;
use Poirot\Core\OpenOptions;
use Poirot\Stream\Interfaces\Context\iSContext;

!defined('POIROT_CORE_LOADED') and include_once 'Core.php';

/**
 * TODO contexts
 */
abstract class AbstractContext extends OpenOptions
    implements
    iSContext,
    iOptionsProvider
{
    protected $wrapper = null;

    // params

    /**
     * @var callable
     */
    protected $notification;

    // options

    /**
     * @var iOptionImplement
     */
    protected $options;

    /**
     * @var array[AbstractContext]
     */
    protected $bindContexts = [];

    /**
     * Construct
     *
     * @param array|iPoirotOptions $options Options
     */
    function __construct($options = null)
    {
        $this->__before_construct();

        parent::__construct($options);
    }

    /**
     * Called by __construct
     */
    protected function __before_construct()
    {

    }

    /**
     * Used To Create Context, as php on creating streams
     * contexts get options as associative array with
     * $arr['wrapper']['option'] = $value format
     *
     * @throws \Exception
     * @return string
     */
    function wrapperName()
    {
        $wrapper = $this->wrapper;
        if ($wrapper === null)
            throw new \Exception('No Wrapper Defined Yet!!');

        return $wrapper;
    }

    /**
     * Bind Another Context Along this
     *
     * [
     * * 'socket' => [
            'bindto' => '192.168.0.100:7000',
        ],
     * * 'http' => [
     *      ...
     *  ]
     * ]
     *
     * @param iSContext|array|resource $context
     *
     * @return $this
     */
    function bindWith($context)
    {
        if (is_array($context))
            $context = stream_context_create($context);

        if (is_resource($context) && get_resource_type($context) == 'stream-context')
            $context = new BaseContext($context);

        if (!$context instanceof iSContext)
            // Invalid parameter
            throw new \InvalidArgumentException(
                "Expecting either a stream context resource or array, got " . gettype($context)
            );


        $this->bindContexts[strtolower($context->wrapperName())] = $context;
        return $this;
    }

    /**
     * Context with specific wrapper has bind?
     *
     * @param string $wrapperName
     *
     * @return false|iSContext
     */
    function hasBind($wrapperName)
    {
        return array_key_exists(strtolower($wrapperName), $this->bindContexts);
    }

    /**
     * List of Wrapper Name Of Currently Bind Contexts
     *
     * @return array[ (string) wrapperName ]
     */
    function listBindContexts()
    {
        return array_keys($this->bindContexts);
    }

    // Params:

    /**
     * Set callback function for the notification context parameter
     * @link http://php.net/manual/en/function.stream-notification-callback.php
     *
     * @param callable $notification
     *
     * @return $this
     */
    public function setNotification($notification)
    {
        if ($notification !== null && !is_callable($notification))
            throw new \InvalidArgumentException('Notification handler must be a callable.');

        $this->notification = $notification;

        return $this;
    }

    /**
     * @return callable
     */
    public function getNotification()
    {
        return $this->notification;
    }

    // Context:

    /**
     * Set/Retrieves specific options
     *
     * @return OpenOptions
{'fraction_non_alphanumeric': 0.11984309481942378, 'fraction_numerical': 0.0037873664277018803, 'mean_word_length': 2.1277495769881556, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '2331105', 'n_tokens_mistral': 2163, 'n_tokens_neox': 2086, 'n_words': 462}