<commit_before><?php
namespace Matisse\Components;

use Matisse\Components\Base\Component;
use Matisse\Parser\Parser;
use Matisse\Properties\Base\ComponentProperties;
use Matisse\Properties\TypeSystem\type;

class IfProperties extends ComponentProperties
{
  /**
   * @var Metadata[]
   */
  public $case = type::collection;
  /**
   * @var Metadata|null
   */
  public $else = type::content;
  /**
   * @var string A regular expression.
   */
  public $matches = '';
  /**
   * @var bool Assigned via the `<If {exp}>` syntax.
   */
  public $nameless = type::bool;
  /**
   * > **Mote:** it doesn't work with databinding.
   *
   * @var bool
   */
  public $not = false;
  /**
   * @var mixed
   */
  public $value = type::any;
}

/**
 * Rendes content blocks conditionally.
 *
 * ##### Syntax:
 * ```
 * <If {exp}>
 *   content if truthy (not null nor an empty string)
 *   <Else> content if falsy </Else>
 * </If>
 *
 * <If value="value"> content if value is truthy </If>    // this is the same as <If {value}>
 *
 * <If not value="value"> content if value is falsy </If> // this is the same as <If {!value}>
 *
 * <If value="value" matches="regexp"> content if value matches the regular expression </If>
 *
 * <If value="value" not matches="regexp"> content if value doesn't match the regular expression </If>
 *
 * <If value="value">
 *   <Case is="value1"> content if value == value1 </Case>
 *   ...
 *   <Case is="valueN"> content if value == valueN </Case>
 *   <Else> content if no match </Else>
 * </If>
 * ```
 */
class If_ extends Component
{
  const allowsChildren = true;

  const propertiesClass = IfProperties::class;

  /** @var IfProperties */
  public $props;

  protected function evaluate ()
  {
    $prop = $this->props;
    $np   = Parser::NAMELESS_PROP;

    if (isset($prop->$np)) {
      if ($prop->$np)
//      if ($prop->getComputed($np))
        return $this->getChildren ();
      return $this->getChildren ('else');
    }

    $v   = $prop->get ('value');
    $not = $prop->not;

    if (exists ($prop->matches)) {
      if (preg_match ("%$prop->matches%", $v) xor $not)
        return $this->getChildren ();
      return $this->getChildren ('else');
    }

    if ($prop->case) {
      foreach ($prop->case as $param) {
        if ($v == $param->props->is)
          return $param->getChildren ();
      }
      return $this->getChildren ('else');
    }

    if (toBool ($v) xor $not)
      return $this->getChildren ();

    return $this->getChildren ('else');
  }

  protected function render ()
  {
    $result = $this->evaluate ();
    if ($result)
      self::renderSet ($result);
  }
}<commit_msg>FIX: <IF {variable}> (instead of <If {variable!=null}>) not working. FIX: other IF issues.<commit_after><?php
namespace Matisse\Components;

use Matisse\Components\Base\Component;
use Matisse\Parser\Parser;
use Matisse\Properties\Base\ComponentProperties;
use Matisse\Properties\TypeSystem\type;

class IfProperties extends ComponentProperties
{
  /**
   * @var Metadata[]
   */
  public $case = type::collection;
  /**
   * @var Metadata|null
   */
  public $else = type::content;
  /**
   * A regular expression. Ex: `'/some .* apples/i'`
   *
   * @var string
   */
  public $matches = '';
  /**
   * @var bool Assigned via the `<If {exp}>` syntax.
   */
  public $nameless = type::any;
  /**
   * > **Mote:** it doesn't work with databinding.
   *
   * @var bool
   */
  public $not = false;
  /**
   * @var mixed
   */
  public $value = type::any;
}

/**
 * Renders content blocks conditionally.
 *
 * ##### Basic syntax:
 * ```
 * <If {exp}>
 *   content if truthy (not null nor an empty string)
 *   <Else>
 *     content if falsy (note: the Else block is optional)
 *   </Else>
 * </If>
 * ```
 * <p>`{exp}` is a databinding expression. Ex: `{some.prop == 5}`
 * <p>Note that when `{exp}` is a string value, it's considered `false` when its value is `'false'`, `'no'`, `'off'`,
 * `'0'` or `''`.
 *
 * ##### Other forms:
 * ```
 * <If value={exp}>                   This is the same as <If {exp}>
 *   content if exp is truthy         You can use either on the examples below.
 * </If>
 *
 * <If not {exp}>                     This is the same as <If {!exp}> or <If not value={exp}>
 *   content if exp is falsy
 * </If>
 *
 * <If {exp} matches="regexp">        This is the same as <If value={exp} matches="regexp">
 *   content if exp matches the regular expression
 * </If>
 *
 * <If {exp} not matches="regexp">    This is the same as <If value={exp} not matches="regexp">
 *   content if exp doesn't match the regular expression
 * </If>
 *
 * <If {exp}>
 *   <Case is=value1>
 *     content if exp == value1
 *   </Case>
 *   ...
 *   <Case is=valueN>
 *     content if exp == valueN
 *   </Case>
 *   <Else>
 *     content if no match (optional)
 *   </Else>
 * </If>
 * ```
 */
class If_ extends Component
{
  const allowsChildren = true;

  const propertiesClass = IfProperties::class;

  /** @var IfProperties */
  public $props;

  /**
   * Evaluates the condition of the If clause.
   *
   * @return bool
   */
  protected function evaluate ()
  {
    $prop = $this->props;
    $np   = Parser::NAMELESS_PROP;
    $v    = isset ($prop->$np) ? $prop->$np : $prop->get ('value');
    $not  = $prop->not;

    if (exists ($prop->matches))
      return (bool)preg_match ("%$prop->matches%", $v) xor $not;

    if ($prop->case) {
      foreach ($prop->case as $param) {
        if ($v == $param->props->get ('is')) // Note that we use the loose comparison operator == here.
          return true;
      }
      return false;
    }

    return strToBool ($v) xor $not;
  }

  protected function render ()
  {
    self::renderSet ($this->getChildren ($this->evaluate () ? null : 'else'));
  }

}
{'fraction_non_alphanumeric': 0.17453405330081867, 'fraction_numerical': 0.0010451140916216688, 'mean_word_length': 2.6526717557251906, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 92, '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': '5794699', 'n_tokens_mistral': 1917, 'n_tokens_neox': 1893, 'n_words': 567}