Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/plugin/alias-cmd.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ protected function createInfo(array $answers): string {
$info['options']['user'] = $answers['user'];
}

return json_encode($info, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . "\n";
return json_encode($info, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . "\n";
}

protected function askAliasFile(string $entry): string {
Expand Down
3 changes: 2 additions & 1 deletion lib/src/Bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Civi\Cv;

use Civi\Cv\Util\Json;
use Civi\Cv\Util\SimulateWeb;

/**
Expand Down Expand Up @@ -170,7 +171,7 @@ public function boot($options = array()) {
if (!defined('CIVICRM_SETTINGS_PATH')) {

$this->options = $options = array_merge($this->options, $options);
$this->log->debug("Options: " . json_encode($options, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$this->log->debug("Options: " . Json::encode($options, 'pretty'));

$this->log->debug("Find settings file");
$settings = $this->getCivicrmSettingsPhp($options);
Expand Down
42 changes: 42 additions & 0 deletions lib/src/Util/Json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Civi\Cv\Util;

class Json {

/**
* @param mixed $value
* @param string $format
* "raw": Similar to PHP default
* "flat": Use a single line. Avoid extraneous escaping. (Suitable for JSON files but not HTML-JSON.)
* "pretty": Use many lines with indentation. Avoid extraneous escaping. (Suitable for JSON files but not HTML-JSON.)
* @param mixed $onFailure
* false: Legacy behavior, return FALSE.
* null: New behavior, return NULL. Easier to string with `??` operator.
* "throw": Generate an exception.
* @return string|false
*/
public static function encode($value, string $format, $onFailure = 'throw') {
$flags = [
'raw' => 0,
'flat' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
'pretty' => JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
];
if (!isset($flags[$format])) {
throw new \LogicException("Invalid JSON format: $format");
}

$options = JSON_THROW_ON_ERROR | $flags[$format];
try {
return json_encode($value, $options);
}
catch (\JsonException $e) {
if ($onFailure === FALSE || $onFailure === NULL) {
fprintf(STDERR, "Failed to encode JSON: %s\n", $e->getMessage());
return $onFailure;
}
throw $e;
}
}

}
5 changes: 3 additions & 2 deletions src/Command/Api4Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Civi\Api4\Generic\Result;
use Civi\Cv\Encoder;
use Civi\Cv\Util\Api4ArgParser;
use Civi\Cv\Util\Json;
use Civi\Cv\Util\StructuredOutputTrait;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -146,12 +147,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int
throw new \RuntimeException("Please enable APIv4 before running APIv4 commands.");
}

list($entity, $action) = explode('.', $input->getArgument('Entity.action'));
[$entity, $action] = explode('.', $input->getArgument('Entity.action'));
$params = $this->parseParams($input);
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE || $input->getOption('dry-run')) {
$output->writeln("{$I}Entity{$_I}: {$C}$entity{$_C}");
$output->writeln("{$I}Action{$_I}: {$C}$action{$_C}");
$output->writeln("{$I}Params{$_I}: " . json_encode($params, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$output->writeln("{$I}Params{$_I}: " . Json::encode($params, 'pretty'));
}
if ($input->getOption('dry-run')) {
return 0;
Expand Down
10 changes: 6 additions & 4 deletions src/Command/ApiBatchCommand.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Civi\Cv\Command;

use Civi\Cv\Util\Json;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -82,7 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

if ($output->isVerbose()) {
fwrite(STDERR, sprintf("Set API defaults: %s\n", json_encode($this->defaults, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)));
fwrite(STDERR, sprintf("Set API defaults: %s\n", Json::encode($this->defaults, 'pretty')));
}

$lineNum = 0;
Expand All @@ -107,15 +108,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$result[$k] = array('is_error' => 1, 'error_message' => "JSON data is structured incorrectly (line $lineNum)");
continue;
}
list ($entity, $action, $params) = $api;
[$entity, $action, $params] = $api;
$params = \CRM_Utils_Array::crmArrayMerge($params, $this->defaults);
if ($output->isVerbose()) {
fwrite(STDERR, sprintf("Execute API calls: %s\n", json_encode([$entity, $action, $params], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)));
fwrite(STDERR, sprintf("Execute API calls: %s\n", Json::encode([$entity, $action, $params], 'pretty')));
}
$result[$k] = \civicrm_api($entity, $action, $params);
}
}
echo json_encode($result);
echo Json::encode($result, 'flat', NULL)
?? Json::encode(['is_error' => 1, 'error_message' => ['API executed, but results cannot be returned']], 'flat');
echo "\n";

if (ob_get_level() > 0) {
Expand Down
5 changes: 3 additions & 2 deletions src/Command/ApiCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Civi\Cv\Command;

use Civi\Cv\Encoder;
use Civi\Cv\Util\Json;
use Civi\Cv\Util\StructuredOutputTrait;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -53,7 +54,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$I = '<info>';
$_I = '</info>';

list($entity, $action) = explode('.', $input->getArgument('Entity.action'));
[$entity, $action] = explode('.', $input->getArgument('Entity.action'));
$params = $this->parseParams($input);

if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE && !array_key_exists('debug', $params)) {
Expand All @@ -63,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
$output->writeln("{$I}Entity{$_I}: {$C}$entity{$_C}");
$output->writeln("{$I}Action{$_I}: {$C}$action{$_C}");
$output->writeln("{$I}Params{$_I}: " . json_encode($params, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$output->writeln("{$I}Params{$_I}: " . Json::encode($params, 'pretty'));
}

$result = \civicrm_api($entity, $action, $params);
Expand Down
3 changes: 2 additions & 1 deletion src/Command/SettingSetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Civi\Cv\Command;

use Civi\Core\SettingsBag;
use Civi\Cv\Util\Json;
use Civi\Cv\Util\SettingTrait;
use Civi\Cv\Util\StructuredOutputTrait;
use Symfony\Component\Console\Input\InputArgument;
Expand Down Expand Up @@ -99,7 +100,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$params = $this->parseSettingParams($input, $settingBag, $meta);
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
$output->writeln("{$I}Params{$_I}: " . json_encode($params, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$output->writeln("{$I}Params{$_I}: " . Json::encode($params, 'pretty'));
}

foreach ($params as $settingKey => $settingValue) {
Expand Down
12 changes: 7 additions & 5 deletions src/Encoder.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?php
namespace Civi\Cv;

use Civi\Cv\Util\Json;

class Encoder {

/**
Expand Down Expand Up @@ -64,14 +66,14 @@ public static function encode($data, $format) {
return var_export(static::preferArray($data), 1);

case 'json-pretty':
$jsonOptions = (defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)
|
(defined('JSON_UNESCAPED_SLASHES') ? JSON_UNESCAPED_SLASHES : 0);
return json_encode($data, $jsonOptions);
return Json::encode($data, 'pretty');

case 'json-flat':
return Json::encode($data, 'flat');

case 'json':
case 'json-strict':
return json_encode($data);
return Json::encode($data, 'raw');

case 'serialize':
return serialize($data);
Expand Down
2 changes: 1 addition & 1 deletion src/Util/Api4ArgEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function encodeParams(array $params = []): array {
}
}
if (!empty($oddballs)) {
$parts[] = json_encode($oddballs);
$parts[] = Json::encode($oddballs, 'raw');
}
return $parts;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Util/ConsoleQueueRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function runAll() {

protected static function formatTaskCallback(\CRM_Queue_Task $task) {
$cb = implode('::', (array) $task->callback);
$args = json_encode($task->arguments, JSON_UNESCAPED_SLASHES);
$args = Json::encode($task->arguments, 'flat', NULL) ?? '(unprintable)';
return sprintf("%s(%s)", $cb, substr($args, 1, -1));
}

Expand Down
2 changes: 1 addition & 1 deletion src/Util/StructuredOutputTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function($value) {
return '';
}
elseif (is_array($value)) {
return json_encode($value, JSON_UNESCAPED_SLASHES);
return Json::encode($value, 'flat', NULL) ?? '(unprintable)';
}
elseif (is_object($value)) {
return '(' . get_class($value) . ')';
Expand Down