Skip to content

Commit fcbd99b

Browse files
committed
Harden type safety and null handling across API and helper services
1 parent 752608b commit fcbd99b

17 files changed

Lines changed: 69 additions & 42 deletions

src/base/Logger.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function __construct()
6363
} else {
6464
throw new ConfigException(t('Error creating logger'));
6565
}
66-
$this->logLevel = strtoupper(Config::getParam('log.level', 'NOTICE'));
66+
$this->logLevel = strtoupper((string)Config::getParam('log.level', 'NOTICE'));
6767
}
6868

6969
public function __destruct()
@@ -163,12 +163,12 @@ public static function log($msg, $type = LOG_DEBUG, $context = null, $force = fa
163163
if (null === $context) {
164164
$context = [];
165165
}
166-
if (Config::getParam('profiling.enable') && 'DEBUG' === Config::getParam('log.level', 'NOTICE')) {
166+
if (Config::getParam('profiling.enable') && 'DEBUG' === (string)Config::getParam('log.level', 'NOTICE')) {
167167
Inspector::stats($msg, Inspector::SCOPE_DEBUG);
168168
}
169169
$level = LogHelper::calculateLogLevel($type);
170170
if (in_array($level, [\Monolog\Level::Critical, \Monolog\Level::Error, \Monolog\Level::Emergency], true) &&
171-
strlen(Config::getParam('log.slack.hook', '')) > 0) {
171+
strlen((string)Config::getParam('log.slack.hook', '')) > 0) {
172172
SlackHelper::getInstance()->trace($msg, '', '', $context);
173173
}
174174
self::getInstance()->addLog($msg, $level, $context, $force);

src/base/Security.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private function authorizeAdminCredentials(array $admins, $user, $token, $pass):
143143
*/
144144
public function canAccessRestrictedAdmin()
145145
{
146-
return (null !== $this->admin && !preg_match('/^\/admin\/login/i', Request::requestUri())) || self::isTest();
146+
return (null !== $this->admin && !preg_match('/^\/admin\/login/i', (string)Request::requestUri())) || self::isTest();
147147
}
148148

149149
/**

src/base/types/Api.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public function post()
187187
Logger::log($e->getMessage(), LOG_CRIT, $context);
188188
}
189189

190-
return $this->json(new JsonResponse($model, $saved, $saved, 0, $message), $status);
190+
return $this->json(new JsonResponse($model, $saved, $saved ? 1 : 0, 0, $message), $status);
191191
}
192192

193193
/**
@@ -241,7 +241,7 @@ public function put($pk)
241241
$message = t('Referenced model for update was not found');
242242
}
243243

244-
return $this->json(new JsonResponse($model, $updated, $updated, 0, $message), $status);
244+
return $this->json(new JsonResponse($model, $updated, $updated ? 1 : 0, 0, $message), $status);
245245
}
246246

247247
/**
@@ -283,7 +283,7 @@ public function delete($pk = null)
283283
}
284284
}
285285

286-
return $this->json(new JsonResponse(null, $deleted, $deleted, 0, $message), ($deleted) ? 200 : 400);
286+
return $this->json(new JsonResponse(null, $deleted, $deleted ? 1 : 0, 0, $message), ($deleted) ? 200 : 400);
287287
}
288288

289289
/**
@@ -321,6 +321,9 @@ private function extractDataWithFormat()
321321
{
322322
$return = [];
323323
$modelPk = ApiHelper::extractPrimaryKeyColumnName($this->getTableMap());
324+
if (!$modelPk instanceof \Propel\Runtime\Map\ColumnMap) {
325+
return $return;
326+
}
324327
foreach ($this->list->getData() as $data) {
325328
$return[] = ApiHelper::mapArrayObject($this->getModelNamespace(), $modelPk, $this->query, $data);
326329
}

src/base/types/CurlService.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,9 @@ protected function setDefaults()
114114
switch (strtoupper($this->type)) {
115115
case Request::VERB_GET:
116116
if (!empty($this->params)) {
117-
$sep = !str_contains($this->getUrl(), '?') ? '?' : '';
118-
$this->setUrl($this->getUrl() . $sep . http_build_query($this->getParams()), false);
117+
$baseUrl = (string)($this->getUrl() ?? '');
118+
$sep = !str_contains($baseUrl, '?') ? '?' : '';
119+
$this->setUrl($baseUrl . $sep . http_build_query($this->getParams()), false);
119120
}
120121
break;
121122
case Request::VERB_POST:
@@ -141,7 +142,8 @@ public function callSrv()
141142
if ($this->isDebug()) {
142143
$verbose = $this->initVerboseMode();
143144
}
144-
$this->setRawResult(curl_exec($this->getCon()));
145+
$rawResult = curl_exec($this->getCon());
146+
$this->setRawResult(is_string($rawResult) ? $rawResult : '');
145147
$this->setResult($this->isJson() ? json_decode($this->getRawResult(), true) : $this->getRawResult());
146148
if ($this->isDebug() && is_resource($verbose)) {
147149
$this->dumpVerboseLogs($verbose);

src/base/types/helpers/AuthHelper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public static function getAdminFromCookie(): array
4747
*/
4848
public static function generateProfileHash(?string $role = AuthHelper::SESSION_TOKEN): string
4949
{
50+
$role = is_string($role) && $role !== '' ? $role : self::SESSION_TOKEN;
5051
return substr($role, 0, 8);
5152
}
5253

@@ -190,7 +191,8 @@ public static function checkJwtAuth(array $admins)
190191
return self::authTuple();
191192
}
192193
try {
193-
$decoded = (array)JWT::decode($token, new Key($hash, Config::getParam('jwt.alg', 'HS256')));
194+
$algorithm = (string)Config::getParam('jwt.alg', 'HS256');
195+
$decoded = (array)JWT::decode($token, new Key($hash, $algorithm));
194196
if ($decoded !== $payload) {
195197
self::logInvalidAuthInput('jwt_payload_mismatch');
196198
return self::authTuple();

src/base/types/helpers/I18nHelper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public static function generateTranslationsFile(string $absoluteFileName): array
5252
public static function setLocale(string $default = null, string $customKey = null, bool $force = false): void
5353
{
5454
$locale = $force ? $default : self::extractLocale($default);
55+
$locale = is_string($locale) && $locale !== '' ? $locale : (string)($default ?: 'en_US');
5556
Inspector::stats('[i18NHelper] Set locale to project [' . $locale . ']', Inspector::SCOPE_DEBUG);
5657
// Load translations
5758
putenv("LC_ALL=" . $locale);
@@ -88,7 +89,7 @@ public static function utf8Encode($data): mixed
8889
$field = self::utf8Encode($field);
8990
}
9091
} elseif (is_object($data)) {
91-
$properties = get_class_vars($data);
92+
$properties = get_class_vars(get_class($data));
9293
if (is_array($properties)) {
9394
foreach (array_keys($properties) as $property) {
9495
$data->$property = self::utf8Encode($data->$property);

src/base/types/helpers/MetadataReader.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,12 @@ public static function extractVarType(?ReflectionProperty $property, ?string $do
6767
self::logLegacyFallback('annotation_var');
6868
}
6969
}
70-
return self::readVarTypeFromDoc($doc ?: '');
70+
$type = self::readVarTypeFromDoc($doc ?: '');
71+
return is_string($type) && trim($type) !== '' ? $type : null;
7172
}
7273

7374
/**
74-
* @return array{
75-
* isInjectable:bool,
76-
* class:?string,
77-
* singleton:bool,
78-
* required:bool,
79-
* source:?string
80-
* }
75+
* @return array<string, mixed>
8176
*/
8277
public static function resolveInjectableDefinition(?ReflectionProperty $property, ?string $doc = ''): array
8378
{
@@ -109,9 +104,10 @@ public static function resolveInjectableDefinition(?ReflectionProperty $property
109104

110105
if ($doc !== '' && preg_match(InjectorHelper::INJECTABLE_PATTERN, $doc) === 1) {
111106
$className = self::readVarTypeFromDoc($doc);
107+
$className = is_string($className) ? $className : '';
112108
return [
113-
'isInjectable' => $className !== null && trim($className) !== '',
114-
'class' => $className,
109+
'isInjectable' => trim($className) !== '',
110+
'class' => trim($className) !== '' ? $className : null,
115111
'singleton' => true,
116112
'required' => true,
117113
'source' => 'annotation',

src/base/types/helpers/SecurityHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private static function mixToken(string $timestamp, string $hash, string $token)
7777
$charsLength = strlen(self::RAND_SEP) - 1;
7878
$tsLength = strlen($timestamp);
7979
$i = 0;
80-
$partCount = ceil($hashRest / 4);
80+
$partCount = (int)ceil($hashRest / 4);
8181
$part = substr($hash, $tsLength + $partCount * $i, $partCount);
8282
while (false !== $part && strlen($part) > 0) {
8383
$mixedToken .= $part .

src/base/types/traits/Api/ApiTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ trait ApiTrait
4040
*/
4141
public function getApi()
4242
{
43-
$model = explode("\\", $this->getModelNamespace());
43+
$model = explode("\\", (string)($this->getModelNamespace() ?? ''));
4444

4545
return $model[count($model) - 1];
4646
}

src/base/types/traits/Api/MutationTrait.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,23 @@ protected function hydrateRequestData()
8686
protected function getModelNamespace()
8787
{
8888
$tableMap = $this->getModelTableMap();
89-
return (null !== $tableMap) ? $tableMap::getOMClass(false) : null;
89+
if (null === $tableMap) {
90+
return null;
91+
}
92+
$map = $tableMap::getTableMap();
93+
$className = $map?->getClassName();
94+
if (is_string($className) && $className !== '') {
95+
return $className;
96+
}
97+
if (method_exists($tableMap, 'getOMClass')) {
98+
try {
99+
$legacyClassName = $tableMap::getOMClass(false);
100+
return is_string($legacyClassName) && $legacyClassName !== '' ? $legacyClassName : null;
101+
} catch (\Throwable) {
102+
// Keep null when table map cannot resolve OM class.
103+
}
104+
}
105+
return null;
90106
}
91107

92108
/**

0 commit comments

Comments
 (0)