/** * @param SplFileInfo $file * * @return mixed * @throws \Seld\JsonLint\ParsingException */ public function lint(SplFileInfo $file) { $errors = new LintErrorsCollection(); $flags = $this->calculateFlags(); try { $json = $this->filesystem->readFromFileInfo($file); $this->jsonParser->parse($json, $flags); } catch (ParsingException $exception) { $errors->add(JsonLintError::fromParsingException($file, $exception)); } return $errors; }
private static function loadConfig(Container $container) { global $argv; $configPaths = array(); foreach ($argv as $arg) { if (0 === strpos($arg, '--config=')) { $configFile = substr($arg, 9); if (!file_exists($configFile)) { echo sprintf('Config file "%s" does not exist', $configFile) . PHP_EOL; exit(1); } $configPaths = array($configFile); } } if (empty($configPaths)) { $configPaths = array(getcwd() . '/phpbench.json', getcwd() . '/phpbench.json.dist'); } foreach ($configPaths as $configPath) { if (!file_exists($configPath)) { continue; } $config = file_get_contents($configPath); try { $parser = new JsonParser(); $parser->parse($config); } catch (ParsingException $e) { echo 'Error parsing config file:' . PHP_EOL . PHP_EOL; echo $e->getMessage(); exit(1); } $config = json_decode($config, true); $config['config_path'] = $configPath; $container->mergeParameters($config); } }
protected function execute(InputInterface $input, OutputInterface $output) { $output->writeln('Running data verification.'); $parser = new JsonParser(); $rootPath = __DIR__ . '/../../..'; $dataFiles = scandir($rootPath . '/data/'); $numFiles = 0; $numErrors = 0; foreach ($dataFiles as $filename) { if (preg_match('/.+\\.json$/i', $filename) === 1) { $numFiles++; $output->writeln(sprintf('#%s Testing %s', $numFiles, $filename)); $json = file_get_contents(sprintf('%s/data/%s', $rootPath, $filename)); try { $return = $parser->parse($json); } catch (Parsing\Exception $e) { $numErrors++; $output->writeln(sprintf(PHP_EOL . ' <error>%s</error>' . PHP_EOL, $e->getMessage())); continue; } $ppData = json_decode($json, true); try { $this->dataIntegrityTest($ppData); } catch (\Exception $e) { $numErrors++; $output->writeln(sprintf(PHP_EOL . ' <error>%s</error>' . PHP_EOL, $e->getMessage())); } } } if ($numErrors !== 0) { $output->writeln(sprintf(PHP_EOL . ' <error>%s errors found!</error>', $numErrors)); } else { $output->writeln(PHP_EOL . '<info>No errors found!</info>'); } }
/** * {@inheritdoc} */ public function parse($content) { try { $parser = new JsonLintParser(); return $parser->parse($content, JsonLintParser::PARSE_TO_ASSOC); } catch (\Exception $e) { throw new ParsingException($this->getMetaParser()->getName(), null, $e); } }
/** * Parse json file into definition format. * * @param string $filename * @return Definition */ public static function loadJSON($filename) { if (!is_readable($filename)) { throw new \RuntimeException('JSON file "' . $filename . '" doesn\'t readable'); } $json = file_get_contents($filename); $parser = new JsonParser(); $parsed = $parser->parse($json); return static::load((array) $parsed); }
private static function loadConfig() { global $argv; $configPaths = array(); $bootstrapOverride = null; $extensions = array(); foreach ($argv as $arg) { if ($configFile = self::parseOption($arg, 'config')) { if (!file_exists($configFile)) { echo sprintf('Config file "%s" does not exist', $configFile) . PHP_EOL; exit(1); } $configPaths = array($configFile); } if ($value = self::parseOption($arg, 'bootstrap', 'b')) { $bootstrapOverride = $value; } if ($value = self::parseOption($arg, 'extension')) { $extensions[] = $value; } } if (empty($configPaths)) { $configPaths = array(getcwd() . '/phpbench.json', getcwd() . '/phpbench.json.dist'); } $config = array('extensions' => array(), 'bootstrap' => null); foreach ($configPaths as $configPath) { if (!file_exists($configPath)) { continue; } $configRaw = file_get_contents($configPath); try { $parser = new JsonParser(); $parser->parse($configRaw); } catch (ParsingException $e) { echo 'Error parsing config file:' . PHP_EOL . PHP_EOL; echo $e->getMessage(); exit(1); } $config = array_merge($config, json_decode($configRaw, true)); $config['config_path'] = $configPath; if ($config['bootstrap']) { $config['bootstrap'] = self::getBootstrapPath(dirname($configPath), $config['bootstrap']); } break; } if ($bootstrapOverride) { $config['bootstrap'] = self::getBootstrapPath(getcwd(), $bootstrapOverride); } // add any manually specified extensions foreach ($extensions as $extension) { $config['extensions'][] = $extension; } return $config; }
/** * @see \Bolt\Database\Migration\Input\InputFileInterface::readFile() */ public function readFile() { $filename = (string) $this->file; if ($this->file->isReadable()) { try { $data = $this->parser->parse(file_get_contents($filename)); $this->import->setData($data); return true; } catch (ParsingException $e) { $this->import->setError(true)->setErrorMessage("File '{$filename}' has invalid JSON!"); $details = $e->getDetails(); foreach ($details as $detail) { $this->import->setErrorMessage($detail); } return false; } } else { $this->import->setError(true)->setErrorMessage("File '{$filename}' not readable!"); return false; } }
/** * Validates the syntax of a JSON string. * * @param string $json * * @throws ParseException */ private static function validateSyntax($json) { $parser = new JsonParser(); try { $parser->parse($json); } catch (ParsingException $e) { throw ParseException::castFromJson($e); } if (json_last_error() === JSON_ERROR_UTF8) { throw new ParseException('JSON parsing failed: ' . static::errorToString(JSON_ERROR_UTF8)); } }
/** * {@inheritdoc} */ public function getValue($key) { $parser = new JsonParser(); $plist = $this->getStoragePath(); $value = Util::run("defaults read \"{$plist}\" {$key}"); try { $parser->lint($json); return $parser->parse($json); } catch (Exception $e) { throw $e; } }
public function load($file_path, $values = array()) { if (!file_exists($file_path) || false === ($data = file_get_contents($file_path))) { throw new RuntimeException(sprintf('Unable to read file: %s', $file_path)); } $parser = new JsonParser(); try { $data = Utils::toArray($parser->parse($this->doReplace($data, $values), true)); } catch (\Exception $e) { throw new \Exception(sprintf('Unable to parse file %s: %s', $file_path, $e->getMessage())); } return $data; }
/** * @param SplFileInfo $file * * @return mixed * @throws \Seld\JsonLint\ParsingException */ public function lint(SplFileInfo $file) { $parser = new JsonParser(); $errors = new LintErrorsCollection(); $flags = $this->calculateFlags(); try { $json = file_get_contents($file->getPathname()); $parser->parse($json, $flags); } catch (ParsingException $exception) { $errors->add(JsonLintError::fromParsingException($file, $exception)); } return $errors; }
public function __construct($app, Filesystem $fs) { $this->app = $app; $this->fs = $fs; $json_parser = new JsonParser(); $this->extensions = ['json' => function ($raw) use($json_parser) { $parsed = $json_parser->parse($raw); return $parsed; }, 'yml' => function ($raw) { $parsed = Yaml::parse($raw, false, false, true); return $parsed; }]; $this->index(); $this->parse(); }
/** * {@inheritdoc} */ public function process(ProcessorConfig $config, $input) { if (!is_string($input)) { throw new UnexpectedTypeException($input, 'string'); } $input = trim($input); if (empty($input)) { return; } try { $parser = new JsonParser(); $array = $parser->parse($input, JsonParser::PARSE_TO_ASSOC); } catch (ParsingException $e) { throw new InputProcessorException('Input does not contain valid JSON: ' . "\n" . $e->getMessage(), 0, $e); } return parent::process($config, $array); }
private static function loadConfig(Container $container) { global $argv; $configPaths = array(); $bootstrapOverride = null; foreach ($argv as $arg) { if ($configFile = self::parseOption($arg, 'config')) { if (!file_exists($configFile)) { echo sprintf('Config file "%s" does not exist', $configFile) . PHP_EOL; exit(1); } $configPaths = array($configFile); } if ($value = self::parseOption($arg, 'bootstrap', 'b')) { $bootstrapOverride = $value; } } if (empty($configPaths)) { $configPaths = array(getcwd() . '/phpbench.json', getcwd() . '/phpbench.json.dist'); } foreach ($configPaths as $configPath) { if (!file_exists($configPath)) { continue; } $config = file_get_contents($configPath); try { $parser = new JsonParser(); $parser->parse($config); } catch (ParsingException $e) { echo 'Error parsing config file:' . PHP_EOL . PHP_EOL; echo $e->getMessage(); exit(1); } $config = json_decode($config, true); $config['config_path'] = $configPath; if (isset($config['bootstrap'])) { $config['bootstrap'] = self::getBootstrapPath(dirname($configPath), $config['bootstrap']); } $container->mergeParameters($config); } if ($bootstrapOverride) { $container->setParameter('bootstrap', self::getBootstrapPath(getcwd(), $bootstrapOverride)); } }
public function prettify() { $parser = new JsonParser(); foreach ($this->files as $file) { $raw = $this->fs->get($file); $data = $parser->parse($raw); $pretty = json_encode($data, JSON_PRETTY_PRINT); $tmp_name = $file . '.tmp'; if ($this->fs->put($tmp_name, $pretty) === false) { throw new \Exception('Couldn\'t write to ' . $tmp_name); } if (!$this->fs->delete($file)) { throw new \Exception('Couldn\'t delete ' . $file); } if (!$this->fs->move($tmp_name, $file)) { throw new \Exception('Couldn\'t rename ' . $tmp_name); } } }
public function load() { $parser = new JsonParser(); $contents = $this->file->fread($this->file->getSize()); try { $options = JsonParser::PARSE_TO_ASSOC; if ($this->getOption('allow_duplicate_keys')) { $options = $options | JsonParser::ALLOW_DUPLICATE_KEYS; } $contents = $parser->parse($contents, $options); } catch (ParsingException $e) { throw new FileNotParseableException($this->filename, 'JSON', $e->getMessage()); } if (is_array($contents)) { $reader = new ArrayReader($contents); return $this->setReader($reader); } throw new FileNotParseableException($this->filename, 'JSON', 'The file is not an array.'); }
/** * @depends testWhitespace */ public function testJSON($games) { try { $parser = new JsonParser(); $games = $parser->parse($games, JsonParser::DETECT_KEY_CONFLICTS + JsonParser::PARSE_TO_ASSOC); } catch (Exception $e) { $this->assertTrue('parsing', $e->getMessage()); } $allowedKeys = array('Hidden' => 'is_bool', 'Beta' => 'is_bool', 'Comment' => 'is_string', 'CommentURL' => 'is_string'); foreach ($games as $appID => $keys) { $this->assertTrue(is_numeric($appID), 'Key "' . $appID . '" must be numeric'); if ($keys === true) { // We're golden! } else { if (is_array($keys)) { $this->assertNotEmpty($keys, '"' . $appID . '" can not be an empty array'); foreach ($keys as $key => $value) { $this->assertArrayHasKey($key, $allowedKeys, 'Invalid key "' . $key . '" in "' . $appID . '"'); $this->assertTrue($allowedKeys[$key]($value), '"' . $key . '" in "' . $appID . '" is not "' . $allowedKeys[$key] . '"'); if ($key === 'Beta') { $this->assertTrue($value, $key . ' key in "' . $appID . '" can only be set to true'); } else { if ($key === 'Hidden') { $this->assertTrue($value, $key . ' key in "' . $appID . '" can only be set to true'); $this->assertArrayNotHasKey('Beta', $keys, 'Beta key can not be used along with Hidden key in "' . $appID . '"'); $this->assertArrayHasKey('Comment', $keys, 'Hidden app "' . $appID . '" must contain a Comment explaining why it was hidden'); } else { if ($key === 'CommentURL') { $this->assertArrayHasKey('Comment', $keys, 'CommentURL key can not be without Comment key in "' . $appID . '"'); $this->assertStringStartsWith('http', $value, 'CommentURL must be an url in "' . $appID . '"'); } } } } } else { $this->assertTrue(false, 'Key "' . $appID . '" has an invalid value'); } } } return $games; }
public function testFileWithBOM() { try { $parser = new JsonParser(); $parser->parse(file_get_contents(dirname(__FILE__) . '/bom.json')); $this->fail('BOM should be detected'); } catch (ParsingException $e) { $this->assertContains('BOM detected', $e->getMessage()); } }
/** * Creates a Composer instance * * @param IOInterface $io IO instance * @param array|string|null $localConfig either a configuration array or a filename to read from, if null it will * read from the default filename * @param bool $disablePlugins Whether plugins should not be loaded * @param bool $fullLoad Whether to initialize everything or only main project stuff (used when loading the global composer) * @throws \InvalidArgumentException * @throws \UnexpectedValueException * @return Composer */ public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true) { $cwd = $cwd ?: getcwd(); // load Composer configuration if (null === $localConfig) { $localConfig = static::getComposerFile(); } if (is_string($localConfig)) { $composerFile = $localConfig; $file = new JsonFile($localConfig, null, $io); if (!$file->exists()) { if ($localConfig === './composer.json' || $localConfig === 'composer.json') { $message = 'Composer could not find a composer.json file in ' . $cwd; } else { $message = 'Composer could not find the config file: ' . $localConfig; } $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section'; throw new \InvalidArgumentException($message . PHP_EOL . $instructions); } $file->validateSchema(JsonFile::LAX_SCHEMA); $jsonParser = new JsonParser(); try { $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS); } catch (\Seld\JsonLint\DuplicateKeyException $e) { $details = $e->getDetails(); $io->writeError('<warning>Key ' . $details['key'] . ' is a duplicate in ' . $localConfig . ' at line ' . $details['line'] . '</warning>'); } $localConfig = $file->read(); } // Load config and override with local config/auth config $config = static::createConfig($io, $cwd); $config->merge($localConfig); if (isset($composerFile)) { $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG); $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json'); if ($localAuthFile->exists()) { $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG); $config->merge(array('config' => $localAuthFile->read())); $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true)); } } $vendorDir = $config->get('vendor-dir'); $binDir = $config->get('bin-dir'); // initialize composer $composer = new Composer(); $composer->setConfig($config); if ($fullLoad) { // load auth configs into the IO instance $io->loadConfiguration($config); } $rfs = self::createRemoteFilesystem($io, $config); // initialize event dispatcher $dispatcher = new EventDispatcher($composer, $io); $composer->setEventDispatcher($dispatcher); // initialize repository manager $rm = $this->createRepositoryManager($io, $config, $dispatcher, $rfs); $composer->setRepositoryManager($rm); // load local repository $this->addLocalRepository($io, $rm, $vendorDir); // force-set the version of the global package if not defined as // guessing it adds no value and only takes time if (!$fullLoad && !isset($localConfig['version'])) { $localConfig['version'] = '1.0.0'; } // load package $parser = new VersionParser(); $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser); $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser); $package = $loader->load($localConfig, 'Composer\\Package\\RootPackage', $cwd); $composer->setPackage($package); // initialize installation manager $im = $this->createInstallationManager(); $composer->setInstallationManager($im); if ($fullLoad) { // initialize download manager $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs); $composer->setDownloadManager($dm); // initialize autoload generator $generator = new AutoloadGenerator($dispatcher, $io); $composer->setAutoloadGenerator($generator); } // add installers to the manager (must happen after download manager is created since they read it out of $composer) $this->createDefaultInstallers($im, $composer, $io); if ($fullLoad) { $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins); $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins); $composer->setPluginManager($pm); $pm->loadInstalledPlugins(); // once we have plugins and custom installers we can // purge packages from local repos if they have been deleted on the filesystem if ($rm->getLocalRepository()) { $this->purgePackages($rm->getLocalRepository(), $im); } } // init locker if possible if ($fullLoad && isset($composerFile)) { $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION) ? substr($composerFile, 0, -4) . 'lock' : $composerFile . '.lock'; $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile)); $composer->setLocker($locker); } return $composer; }
/** * Creates statements from the content of the request. * @param [String => mixed] $options * @param Callable|null $modifier A function that modifies the statements before storing them. * @return AssocArray Result of storing the statements. */ private function createStatements($options, callable $modifier = null) { Helpers::validateAtom(new XApiImt(explode(';', LockerRequest::header('Content-Type'))[0])); // Gets parts of the request. $parts = $this->getParts(); $content = $parts['content']; // Decodes $statements from $content. try { if (Config::get('xapi.disable_duplicate_key_checks') !== true) { // Check incoming statements for duplicate keys and throw an error if found $jsonParser = new JsonParser(); $jsonParser->parse($content, JsonParser::DETECT_KEY_CONFLICTS); // this will catch any parsing issues } $statements = json_decode($content); if ($statements === null && $content !== '') { throw new Exceptions\Exception('Invalid JSON'); } else { if ($statements === null) { $statements = []; } } } catch (\Seld\JsonLint\DuplicateKeyException $e) { $details = $e->getDetails(); throw new Exceptions\Exception(sprintf('Invalid JSON: `%s` is a duplicate key on line %s', $details['key'], $details['line'])); } catch (\Exception $e) { // some other parsing error occured throw new Exceptions\Exception('Invalid JSON: JSON could not be parsed'); } // Ensures that $statements is an array. if (!is_array($statements)) { $statements = [$statements]; } // Runs the modifier if there is one and there are statements. if (count($statements) > 0 && $modifier !== null) { $statements = $modifier($statements); } // Saves $statements with attachments. return $this->statements->store($statements, is_array($parts['attachments']) ? $parts['attachments'] : [], array_merge(['authority' => $this->getAuthority($options['client'])], $options)); }
function loadJsonFile($filepath, $charset = 'UTF-8') { // Load JSON file $data = @file_get_contents($filepath); if (false === $data) { return NULL; } // Encode to UTF-8 if ('UTF-8' != mb_detect_encoding($data, 'UTF-8', true)) { $data = utf8_encode($data); } // Clean $data = cleanJsonString($data); // Parse JSON try { $parser = new JsonParser(); $knowledge = $parser->parse($data, JsonParser::ALLOW_DUPLICATE_KEYS); } catch (ParsingException $e) { return NULL; } return $knowledge; }
public function loadJsonFile($filepath, $charset = 'UTF-8') { // Load JSON file $data = @file_get_contents($filepath); if (false === $data) { self::$logger->addWarning('Can\'t load JSON file "' . $filepath . '"'); return NULL; } // Encode to UTF-8 if ('UTF-8' != mb_detect_encoding($data, 'UTF-8', true)) { $data = utf8_encode($data); } // Clean $data = cleanJsonString($data); // Parse JSON try { $parser = new JsonParser(); $knowledge = $parser->parse($data, JsonParser::ALLOW_DUPLICATE_KEYS); } catch (ParsingException $e) { self::$logger->addWarning('Can\'t parse JSON file "' . $filepath . '": ' . $e->getMessage()); return NULL; } return $knowledge; }
public function testDuplicateKeysWithEmpty() { $parser = new JsonParser(); $result = $parser->parse('{"":"a", "_empty_":"b"}', JsonParser::ALLOW_DUPLICATE_KEYS); $this->assertThat($result, $this->logicalAnd($this->arrayHasKey('_empty_'), $this->arrayHasKey('_empty_.1'))); }
<?php use Knp\Snappy\Pdf; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; use Seld\JsonLint\JsonParser; use Symfony\Component\PropertyAccess\PropertyAccess; //Request::setTrustedProxies(array('127.0.0.1')); $app->post('/', function (Request $request) use($app) { $parser = new JsonParser(); $accessor = PropertyAccess::createPropertyAccessor(); $snappy = new Pdf(); $snappy->setBinary($app['wkhtmltopdf.binary']); $parameters = $parser->parse($request->getContent()); if ($accessor->isReadable($parameters, 'options')) { foreach ((array) $accessor->getValue($parameters, 'options') as $name => $value) { $snappy->setOption($name, $value); } } $app['tmpFile'] = sys_get_temp_dir() . '/' . md5($request->getContent()); if ($accessor->isReadable($parameters, 'source.url')) { $dns = new Net_DNS2_Resolver(); $dns->query(parse_url($accessor->getValue($parameters, 'source.url'), PHP_URL_HOST)); $snappy->generate($accessor->getValue($parameters, 'source.url'), $app['tmpFile'], [], true); } elseif ($accessor->isReadable($parameters, 'source.html')) { $snappy->generateFromHtml($accessor->getValue($parameters, 'source.html'), $app['tmpFile'], [], true); } elseif ($accessor->isReadable($parameters, 'source.base64')) { $snappy->generateFromHtml(base64_decode($accessor->getValue($parameters, 'source.base64')), $app['tmpFile'], [], true); } return new BinaryFileResponse($app['tmpFile']);
/** * @depends testWhitespace */ public function testJSON($games) { try { $parser = new JsonParser(); $games = $parser->parse($games, JsonParser::DETECT_KEY_CONFLICTS + JsonParser::PARSE_TO_ASSOC); } catch (Exception $e) { $this->assertTrue('parsing', $e->getMessage()); } // TODO make better is_ tests for mixed fields $allowedKeys = array('appid' => 'is_set', 'title' => 'is_string', 'duplicate' => 'is_npcommid', 'note' => 'is_string', 'map' => 'is_set', 'offset' => 'is_string'); foreach ($games as $appID => $keys) { $this->assertTrue(is_npcommid($appID), 'Key "' . $appID . '" must be a Sony game ID'); if (is_array($keys)) { $this->assertNotEmpty($keys, '"' . $appID . '" can not be an empty array'); foreach ($keys as $key => $value) { $this->assertArrayHasKey($key, $allowedKeys, 'Invalid key "' . $key . '" for "' . $appID . '"'); $this->assertTrue($allowedKeys[$key]($value), '"' . $key . '" for "' . $appID . '" is not "' . $allowedKeys[$key] . '"'); if ($key === 'appid') { if (is_array($value)) { $this->assertNotEmpty($value, '"' . $key . '" can not be an empty array'); foreach ($value as $steamappid) { $this->assertTrue(is_appid($steamappid), 'Value "' . $steamappid . '" in "' . $key . '" for "' . $appID . '" must be a valid Steam appid'); } } else { $this->assertTrue(is_appid($value), 'Value "' . $value . '" in "' . $key . '" for "' . $appID . '" must be a valid Steam appid'); } } else { if ($key === 'note') { $this->assertNotEmpty($value, '"' . $key . '" for "' . $appID . '" can not be an empty string'); } else { if ($key === 'map') { if (is_string($value)) { if (strpos($value, '%d') !== false) { /* We are a direct mapping of 0 → name_0, 1 → name_1 */ } else { if (strpos($value, '%02d') !== false) { /* We are a direct mapping of 0 → name_00, 1 → name_01 */ } else { $this->assertTrue(false, 'Value "' . $value . '" for "map" is not a valid map string'); } } } else { if (is_bool($value)) { // for direct mappings, we use "map": false // XXX rework this to confirm NO map exists $this->assertTrue($value === false, 'Key "' . $key . '" for "' . $appID . '" is not a valid value'); } else { if (is_list($value)) { $this->assertNotEmpty($value, 'Key "' . $key . '" for "' . $appID . '" can not be an empty array'); // XXX: Found the first title that mapped Platinum to a Steam achievement, Trine! // $this->assertFalse( array_key_exists( "0", $value ), '"' . $key . '" for "' . $appID . '" has an achievement mapped to Platinum trophy' ); // Discover is we are a multi-grouped map foreach ($value as $index => $group) { if (is_string($group)) { } else { if (is_assoc($group)) { // Our current process makes this recursive for an extra level… // XXX break out duplicate test } else { if (is_list($group)) { // Find accidental duplicates, remove "-1" entries and flatten multiple pairings $valuesmapped = array_values($group); foreach ($valuesmapped as $index => $achievement) { if ($achievement == "-1") { unset($valuesmapped[$index]); } if (is_array($achievement)) { $valuesmapped[$index] = implode("-", $achievement); } } $this->assertTrue(count($valuesmapped) === count(array_unique($valuesmapped)), '"' . $key . '" for "' . $appID . '" has a duplicate mapping'); unset($valuesmapped); } } } } } else { // XXX We should never get here } } } } else { if ($key === 'offset') { // XXX verify "map" is set, and is using "%d" format // XXX validate info inside to support: // -count : basically to mask the current count (starts with 0) // [+-][0-9]* : the offset to the passed in count } } } } } } else { $this->assertTrue(false, 'Value "' . $appID . '" has an invalid value'); } } return $games; }