/home/complianthowden/public_html/vendor/sentry/sentry/src/Serializer/AbstractSerializer.php
<?php

declare(strict_types=1);

/*
 * Copyright 2012 Facebook, Inc.
 *
 * Licensed 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.
*/

namespace Sentry\Serializer;

use Sentry\Exception\InvalidArgumentException;
use Sentry\Options;

/**
 * This helper is based on code from Facebook's Phabricator project.
 *
 *   https://github.com/facebook/phabricator
 *
 * Specifically, it is an adaptation of the PhutilReadableSerializer class.
 */
abstract class AbstractSerializer
{
    /**
     * The default mb detect order.
     *
     * @see http://php.net/manual/en/function.mb-detect-encoding.php
     */
    public const DEFAULT_MB_DETECT_ORDER = 'auto';

    /**
     * Suggested detect order for western countries.
     */
    public const WESTERN_MB_DETECT_ORDER = 'UTF-8, ASCII, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, Windows-1251, Windows-1252, Windows-1254';

    /**
     * The maximum depth to reach when serializing recursively.
     *
     * @var int
     */
    private $maxDepth;

    /**
     * This is the default mb detect order for the detection of encoding.
     *
     * @var string
     */
    protected $mbDetectOrder = self::DEFAULT_MB_DETECT_ORDER;

    /**
     * @var bool Flag to enable serialization of objects internal properties
     */
    protected $serializeAllObjects = false;

    /**
     * @var Options The Sentry options
     */
    protected $options;

    /**
     * AbstractSerializer constructor.
     *
     * @param Options $options The SDK configuration options
     */
    public function __construct(Options $options, int $maxDepth = 3, ?string $mbDetectOrder = null)
    {
        $this->maxDepth = $maxDepth;

        if (null != $mbDetectOrder) {
            $this->mbDetectOrder = $mbDetectOrder;
        }

        $this->options = $options;
    }

    /**
     * Serialize an object (recursively) into something safe for data
     * sanitization and encoding.
     *
     * @param mixed $value
     *
     * @return string|bool|float|int|mixed[]|null
     */
    protected function serializeRecursively($value, int $_depth = 0)
    {
        try {
            if ($_depth >= $this->maxDepth) {
                return $this->serializeValue($value);
            }

            try {
                if (@\is_callable($value)) {
                    return $this->serializeCallable($value);
                }
            } catch (\Throwable $exception) {
                // Do nothing on purpose
            }

            if (\is_array($value)) {
                $serializedArray = [];

                foreach ($value as $k => $v) {
                    $serializedArray[$k] = $this->serializeRecursively($v, $_depth + 1);
                }

                return $serializedArray;
            }

            if (\is_object($value)) {
                $classSerializers = $this->resolveClassSerializers($value);

                // Try each serializer until there is none left or the serializer returned data
                foreach ($classSerializers as $classSerializer) {
                    try {
                        $serializedObjectData = $classSerializer($value);

                        if (\is_array($serializedObjectData)) {
                            return [
                                'class' => \get_class($value),
                                'data' => $this->serializeRecursively($serializedObjectData, $_depth + 1),
                            ];
                        }
                    } catch (\Throwable $e) {
                        // Ignore any exceptions generated by a class serializer
                    }
                }

                if ($this->serializeAllObjects || ($value instanceof \stdClass)) {
                    return $this->serializeObject($value, $_depth);
                }
            }

            return $this->serializeValue($value);
        } catch (\Throwable $error) {
            if (\is_string($value)) {
                return $value . ' {serialization error}';
            }

            return '{serialization error}';
        }
    }

    /**
     * Find class serializers for a object.
     *
     * Registered serializers with the `class_serializers` option take precedence over
     * objects implementing the `SerializableInterface`.
     *
     * @param object $object
     *
     * @return array<int, callable>
     */
    protected function resolveClassSerializers($object): array
    {
        $serializers = [];

        foreach ($this->options->getClassSerializers() as $type => $serializer) {
            if ($object instanceof $type) {
                $serializers[] = $serializer;
            }
        }

        if ($object instanceof SerializableInterface) {
            $serializers[] = static function (SerializableInterface $object): ?array {
                return $object->toSentry();
            };
        }

        return $serializers;
    }

    /**
     * @param object   $object
     * @param string[] $hashes
     *
     * @return mixed[]|string|bool|float|int|null
     */
    protected function serializeObject($object, int $_depth = 0, array $hashes = [])
    {
        if ($_depth >= $this->maxDepth || \in_array(spl_object_hash($object), $hashes, true)) {
            return $this->serializeValue($object);
        }

        $hashes[] = spl_object_hash($object);
        $serializedObject = [];

        foreach ($object as $key => &$value) {
            if (\is_object($value)) {
                $serializedObject[$key] = $this->serializeObject($value, $_depth + 1, $hashes);
            } else {
                $serializedObject[$key] = $this->serializeRecursively($value, $_depth + 1);
            }
        }

        return $serializedObject;
    }

    /**
     * Serializes the given value to a string.
     *
     * @param mixed $value The value to serialize
     */
    protected function serializeString($value): string
    {
        $value = (string) $value;

        // we always guarantee this is coerced, even if we can't detect encoding
        if ($currentEncoding = mb_detect_encoding($value, $this->mbDetectOrder)) {
            $value = mb_convert_encoding($value, 'UTF-8', $currentEncoding);
        } else {
            $value = mb_convert_encoding($value, 'UTF-8');
        }

        if (mb_strlen($value) > $this->options->getMaxValueLength()) {
            $value = mb_substr($value, 0, $this->options->getMaxValueLength() - 10, 'UTF-8') . ' {clipped}';
        }

        return $value;
    }

    /**
     * @param mixed $value
     *
     * @return string|bool|float|int|null
     */
    protected function serializeValue($value)
    {
        if ((null === $value) || \is_bool($value) || is_numeric($value)) {
            return $value;
        }

        if (\is_object($value)) {
            $reflection = new \ReflectionObject($value);

            $objectId = null;
            if ($reflection->hasProperty('id') && ($idProperty = $reflection->getProperty('id'))->isPublic()) {
                $objectId = $idProperty->getValue($value);
            } elseif ($reflection->hasMethod('getId') && ($getIdMethod = $reflection->getMethod('getId'))->isPublic()) {
                try {
                    $objectId = $getIdMethod->invoke($value);
                } catch (\Throwable $e) {
                    // Do nothing on purpose
                }
            }

            return 'Object ' . $reflection->getName() . (is_scalar($objectId) ? '(#' . $objectId . ')' : '');
        }

        if (\is_resource($value)) {
            return 'Resource ' . get_resource_type($value);
        }

        try {
            if (\is_callable($value)) {
                return $this->serializeCallable($value);
            }
        } catch (\Throwable $exception) {
            // Do nothing on purpose
        }

        if (\is_array($value)) {
            return 'Array of length ' . \count($value);
        }

        return $this->serializeString($value);
    }

    /**
     * @param callable|mixed $callable
     */
    protected function serializeCallable($callable): string
    {
        if (\is_string($callable) && !\function_exists($callable)) {
            return $callable;
        }

        if (!\is_callable($callable)) {
            throw new InvalidArgumentException(sprintf('Expecting callable, got %s', \is_object($callable) ? \get_class($callable) : \gettype($callable)));
        }

        try {
            if (\is_array($callable)) {
                $reflection = new \ReflectionMethod($callable[0], $callable[1]);
                $class = $reflection->getDeclaringClass();
            } elseif ($callable instanceof \Closure || (\is_string($callable) && \function_exists($callable))) {
                $reflection = new \ReflectionFunction($callable);
                $class = null;
            } elseif (\is_object($callable) && method_exists($callable, '__invoke')) {
                $reflection = new \ReflectionMethod($callable, '__invoke');
                $class = $reflection->getDeclaringClass();
            } else {
                throw new \InvalidArgumentException('Unrecognized type of callable');
            }
        } catch (\ReflectionException $exception) {
            return '{unserializable callable, reflection error}';
        }

        $callableType = $reflection->isClosure() ? 'Lambda ' : 'Callable ';
        $callableReturnType = $reflection->getReturnType();

        if ($callableReturnType instanceof \ReflectionNamedType) {
            $callableType .= $callableReturnType->getName() . ' ';
        }

        if ($class) {
            $callableType .= $class->getName() . '::';
        }

        return $callableType . $reflection->getName() . ' ' . $this->serializeCallableParameters($reflection);
    }

    private function serializeCallableParameters(\ReflectionFunctionAbstract $reflection): string
    {
        $params = [];
        foreach ($reflection->getParameters() as &$param) {
            $reflectionType = $param->getType();
            if ($reflectionType instanceof \ReflectionNamedType) {
                $paramType = $reflectionType->getName();
            } else {
                $paramType = 'mixed';
            }

            if ($param->allowsNull()) {
                $paramType .= '|null';
            }

            $paramName = ($param->isPassedByReference() ? '&' : '') . $param->getName();

            if ($param->isOptional()) {
                $paramName = '[' . $paramName . ']';
            }

            $params[] = $paramType . ' ' . $paramName;
        }

        return '[' . implode('; ', $params) . ']';
    }

    public function getMbDetectOrder(): string
    {
        return $this->mbDetectOrder;
    }

    /**
     * @return $this
     */
    public function setMbDetectOrder(string $mbDetectOrder): self
    {
        $this->mbDetectOrder = $mbDetectOrder;

        return $this;
    }

    public function setSerializeAllObjects(bool $value): void
    {
        $this->serializeAllObjects = $value;
    }

    public function getSerializeAllObjects(): bool
    {
        return $this->serializeAllObjects;
    }
}
Customer Complaint Form | Howden Indonesia - Official Working Website

CUSTOMER COMPLAINT FORM

Please use this form to give us suggestions, compliments or complaints.
Click here to check complaint status.
Click here to show Term of Business Agreement
Howden


Notes: *.png, *.jpg, *.jpeg, *.pdf, *.doc, *.docx, *.xls, *.xlsx, *.ppt, *.pptx, *.eml are allowed, and size must be smaller than 5Mb.

Copyright © 2026 PT. Howden Insurance Brokers Indonesia. All rights reserved.
Authorised and regulated by Otoritas Jasa Keuangan (OJK).
Member of The Association of Indonesian Insurance & Reinsurance Brokers (APPARINDO).