<commit_before><?php
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/**
 * The Gadget Factory builds a gadget based on the current context and token and returns a fully processed
 * gadget ready to be rendered.
 *
 */
class GadgetFactory {
  /**
   * @var GadgetContext
   */
  private $context;
  private $token;

  public function __construct(GadgetContext $context, $token) {
    $this->context = $context;
    $this->token = $token;
  }

  /**
   * Returns the processed gadget spec
   *
   * @return GadgetSpec
   */
  public function createGadget() {
    $gadgetUrl = $this->context->getUrl();
    if ($this->context->getBlacklist() != null && $this->context->getBlacklist()->isBlacklisted($gadgetUrl)) {
      throw new GadgetException("The Gadget ($gadgetUrl) is blacklisted and can not be rendered");
    }
    // Fetch the gadget's content and create a GadgetSpec
    $gadgetContent = $this->fetchGadget($gadgetUrl);
    $gadgetSpecParser = new GadgetSpecParser();
    $gadgetSpec = $gadgetSpecParser->parse($gadgetContent);
    $gadget = new Gadget($gadgetSpec, $this->context);

    // Process the gadget: fetching remote resources, processing & applying the correct translations, user prefs and feature resolving
    $this->fetchResources($gadget);
    $this->mergeLocales($gadget);
    $this->parseUserPrefs($gadget);
    $this->addSubstitutions($gadget);
    $this->applySubstitutions($gadget);
    $this->parseFeatures($gadget);
    return $gadget;
  }

  /**
   * Resolves the Required and Optional features and their dependencies into a real feature list using
   * the GadgetFeatureRegistry, which can be used to construct the javascript for the gadget
   *
   * @param Gadget $gadget
   */
  private function parseFeatures(Gadget &$gadget) {
    $found = $missing = array();
    if (!$this->context->getRegistry()->resolveFeatures(array_merge($gadget->gadgetSpec->requiredFeatures, $gadget->gadgetSpec->optionalFeatures), $found, $missing)) {
      $requiredMissing = false;
      foreach ($missing as $featureName) {
        if (in_array($featureName, $gadget->gadgetSpec->requiredFeatures)) {
          $requiredMissing = true;
          break;
        }
      }
      if ($requiredMissing) {
        throw new GadgetException("Unknown features: ".implode(',', $missing));
      }
    }
    unset($gadget->gadgetSpec->optionalFeatures);
    unset($gadget->gadgetSpec->requiredFeatures);
    $gadget->features = $found;
  }

  /**
   * Applies the substitutions to the complex types (preloads, user prefs, etc). Simple
   * types (author, title, etc) are translated on the fly in the gadget's getFoo() functions
   */
  private function applySubstitutions(Gadget &$gadget) {
    // Apply the substitutions to the UserPrefs
    foreach ($gadget->gadgetSpec->userPrefs as $key => $pref) {
      $gadget->gadgetSpec->userPrefs[$key]['name'] = $gadget->substitutions->substitute($pref['name']);
      $gadget->gadgetSpec->userPrefs[$key]['displayName'] = $gadget->substitutions->substitute($pref['displayName']);
      $gadget->gadgetSpec->userPrefs[$key]['required'] = $gadget->substitutions->substitute($pref['required']);
      $gadget->gadgetSpec->userPrefs[$key]['datatype'] = $gadget->substitutions->substitute($pref['datatype']);
      $gadget->gadgetSpec->userPrefs[$key]['defaultValue'] = $gadget->substitutions->substitute($pref['defaultValue']);
      $gadget->gadgetSpec->userPrefs[$key]['value'] = $gadget->substitutions->substitute($pref['value']);
      if (isset($pref['enumValues'])) {
        foreach ($pref['enumValues'] as $enumKey => $enumVal) {
          $gadget->gadgetSpec->userPrefs[$key]['enumValues'][$enumKey]['value'] = $gadget->substitutions->substitute($enumVal['value']);
          $gadget->gadgetSpec->userPrefs[$key]['enumValues'][$enumKey]['displayValue'] = $gadget->substitutions->substitute($enumVal['displayValue']);
        }
      }
    }
    // Apply substitutions to the preloads
    foreach ($gadget->gadgetSpec->preloads as $url => $preload) {
      $gadget->gadgetSpec->preloads[$url]['body'] = $gadget->substitutions->substitute($preload['body']);
    }
  }

  /**
   * Seeds the substitutions class with the user prefs, messages, bidi and module id
   */
  private function addSubstitutions(Gadget &$gadget) {
    $gadget->substitutions = new Substitutions();
    if ($this->token) {
      $gadget->substitutions->addSubstitution('MODULE', "ID", $this->token->getModuleId());
    }
    if ($gadget->gadgetSpec->locales) {
      $gadget->substitutions->addSubstitutions('MSG', $gadget->gadgetSpec->locales);
    }
    $gadget->substitutions->addSubstitution('BIDI', "START_EDGE", $gadget->rightToLeft ? "right" : "left");
    $gadget->substitutions->addSubstitution('BIDI', "END_EDGE", $gadget->rightToLeft ? "left" : "right");<commit_msg>Add a zero value module id to the substitutions so translations behave well even if no token is present on the render iframe url<commit_after><?php
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/**
 * The Gadget Factory builds a gadget based on the current context and token and returns a fully processed
 * gadget ready to be rendered.
 *
 */
class GadgetFactory {
  /**
   * @var GadgetContext
   */
  private $context;
  private $token;

  public function __construct(GadgetContext $context, $token) {
    $this->context = $context;
    $this->token = $token;
  }

  /**
   * Returns the processed gadget spec
   *
   * @return GadgetSpec
   */
  public function createGadget() {
    $gadgetUrl = $this->context->getUrl();
    if ($this->context->getBlacklist() != null && $this->context->getBlacklist()->isBlacklisted($gadgetUrl)) {
      throw new GadgetException("The Gadget ($gadgetUrl) is blacklisted and can not be rendered");
    }
    // Fetch the gadget's content and create a GadgetSpec
    $gadgetContent = $this->fetchGadget($gadgetUrl);
    $gadgetSpecParser = new GadgetSpecParser();
    $gadgetSpec = $gadgetSpecParser->parse($gadgetContent);
    $gadget = new Gadget($gadgetSpec, $this->context);

    // Process the gadget: fetching remote resources, processing & applying the correct translations, user prefs and feature resolving
    $this->fetchResources($gadget);
    $this->mergeLocales($gadget);
    $this->parseUserPrefs($gadget);
    $this->addSubstitutions($gadget);
    $this->applySubstitutions($gadget);
    $this->parseFeatures($gadget);
    return $gadget;
  }

  /**
   * Resolves the Required and Optional features and their dependencies into a real feature list using
   * the GadgetFeatureRegistry, which can be used to construct the javascript for the gadget
   *
   * @param Gadget $gadget
   */
  private function parseFeatures(Gadget &$gadget) {
    $found = $missing = array();
    if (!$this->context->getRegistry()->resolveFeatures(array_merge($gadget->gadgetSpec->requiredFeatures, $gadget->gadgetSpec->optionalFeatures), $found, $missing)) {
      $requiredMissing = false;
      foreach ($missing as $featureName) {
        if (in_array($featureName, $gadget->gadgetSpec->requiredFeatures)) {
          $requiredMissing = true;
          break;
        }
      }
      if ($requiredMissing) {
        throw new GadgetException("Unknown features: ".implode(',', $missing));
      }
    }
    unset($gadget->gadgetSpec->optionalFeatures);
    unset($gadget->gadgetSpec->requiredFeatures);
    $gadget->features = $found;
  }

  /**
   * Applies the substitutions to the complex types (preloads, user prefs, etc). Simple
   * types (author, title, etc) are translated on the fly in the gadget's getFoo() functions
   */
  private function applySubstitutions(Gadget &$gadget) {
    // Apply the substitutions to the UserPrefs
    foreach ($gadget->gadgetSpec->userPrefs as $key => $pref) {
      $gadget->gadgetSpec->userPrefs[$key]['name'] = $gadget->substitutions->substitute($pref['name']);
      $gadget->gadgetSpec->userPrefs[$key]['displayName'] = $gadget->substitutions->substitute($pref['displayName']);
      $gadget->gadgetSpec->userPrefs[$key]['required'] = $gadget->substitutions->substitute($pref['required']);
      $gadget->gadgetSpec->userPrefs[$key]['datatype'] = $gadget->substitutions->substitute($pref['datatype']);
      $gadget->gadgetSpec->userPrefs[$key]['defaultValue'] = $gadget->substitutions->substitute($pref['defaultValue']);
      $gadget->gadgetSpec->userPrefs[$key]['value'] = $gadget->substitutions->substitute($pref['value']);
      if (isset($pref['enumValues'])) {
        foreach ($pref['enumValues'] as $enumKey => $enumVal) {
          $gadget->gadgetSpec->userPrefs[$key]['enumValues'][$enumKey]['value'] = $gadget->substitutions->substitute($enumVal['value']);
          $gadget->gadgetSpec->userPrefs[$key]['enumValues'][$enumKey]['displayValue'] = $gadget->substitutions->substitute($enumVal['displayValue']);
        }
      }
    }
    // Apply substitutions to the preloads
    foreach ($gadget->gadgetSpec->preloads as $url => $preload) {
      $gadget->gadgetSpec->preloads[$url]['body'] = $gadget->substitutions->substitute($preload['body']);
    }
  }

  /**
   * Seeds the substitutions class with the user prefs, messages, bidi and module id
   */
  private function addSubstitutions(Gadget &$gadget) {
    $gadget->substitutions = new Substitutions();
    if ($this->token) {
      $gadget->substitutions->addSubstitution('MODULE', "ID", $this->token->getModuleId());
    } else {
      $gadget->substitutions->addSubstitution('MODULE', "ID", 0);
    }
    if ($gadget->gadgetSpec->locales) {
      $gadget->substitutions->addSubstitutions('MSG', $gadget->gadgetSpec->locales);
    }
    $gadget->substitutions->addSubstitution('BIDI', "START_EDGE", $gadget->rightToLeft ? "right" : "left");
    $gadget->substitutions->addSubstitution('BIDI', "END_EDGE", $gadget->rightToLeft ? "left" : "right");
{'fraction_non_alphanumeric': 0.1442443502824859, 'fraction_numerical': 0.0007944915254237289, 'mean_word_length': 4.089398023360287, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 191, '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': '2627046', 'n_tokens_mistral': 3388, 'n_tokens_neox': 3445, 'n_words': 838}