Changeset View
Changeset View
Standalone View
Standalone View
src/xsprintf/PhutilQueryString.php
<?php | <?php | ||||
final class PhutilQueryString extends Phobject { | final class PhutilQueryString extends Phobject { | ||||
private $escaper; | private $maskedString; | ||||
private $argv; | private $unmaskedString; | ||||
public function __construct(PhutilQsprintfInterface $escaper, array $argv) { | public function __construct(PhutilQsprintfInterface $escaper, array $argv) { | ||||
$this->escaper = $escaper; | // Immediately render the query into a static scalar value. | ||||
$this->argv = $argv; | |||||
// This makes sure we throw immediately if there are errors in the | // This makes sure we throw immediately if there are errors in the | ||||
// parameters. | // parameters, which is much better than throwing later on. | ||||
$this->getMaskedString(); | |||||
// This also makes sure that later mutations to objects passed as | |||||
// parameters won't affect the outcome. Consider: | |||||
// | |||||
// $object->setTableName('X'); | |||||
// $query = qsprintf($conn, '%R', $object); | |||||
// $object->setTableName('Y'); | |||||
// | |||||
// We'd like "$query" to reference "X", reflecting the object as it | |||||
// existed when it was passed to "qsprintf(...)". It's surprising if the | |||||
// modification to the object after "qsprintf(...)" can affect "$query". | |||||
$masked_string = xsprintf( | |||||
'xsprintf_query', | |||||
array( | |||||
'escaper' => $escaper, | |||||
'unmasked' => false, | |||||
), | |||||
$argv); | |||||
$unmasked_string = xsprintf( | |||||
'xsprintf_query', | |||||
array( | |||||
'escaper' => $escaper, | |||||
'unmasked' => true, | |||||
), | |||||
$argv); | |||||
$this->maskedString = $masked_string; | |||||
$this->unmaskedString = $unmasked_string; | |||||
} | } | ||||
public function __toString() { | public function __toString() { | ||||
return $this->getMaskedString(); | return $this->getMaskedString(); | ||||
} | } | ||||
public function getUnmaskedString() { | public function getUnmaskedString() { | ||||
return $this->renderString(true); | return $this->unmaskedString; | ||||
} | } | ||||
public function getMaskedString() { | public function getMaskedString() { | ||||
return $this->renderString(false); | return $this->maskedString; | ||||
} | |||||
private function renderString($unmasked) { | |||||
return xsprintf( | |||||
'xsprintf_query', | |||||
array( | |||||
'escaper' => $this->escaper, | |||||
'unmasked' => $unmasked, | |||||
), | |||||
$this->argv); | |||||
} | } | ||||
} | } |