Files
espocrm/application/Espo/Core/Fields/PhoneNumberGroup.php
Yuri Kuznetsov 168f37dc8a doc fix
2021-04-25 11:25:45 +03:00

300 lines
6.9 KiB
PHP

<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Fields;
use RuntimeException;
/**
* A phone number group. Contains a list of phone numbers. One phone number is set as primary.
* If not empty, then there always should be a primary number. Immutable.
*/
class PhoneNumberGroup
{
/**
* @var array<int, PhoneNumber>
*/
private $list = [];
/**
* @var ?PhoneNumber
*/
private $primary = null;
/**
* @param array<int, PhoneNumber> $list
*
* @throws RuntimeException
*/
public function __construct(array $list = [])
{
foreach ($list as $item) {
$this->list[] = clone $item;
}
$this->validateList();
if (count($this->list) !== 0) {
$this->primary = $this->list[0];
}
}
public function __clone()
{
$newList = [];
foreach ($this->list as $item) {
$newList[] = clone $item;
}
$this->list = $newList;
if ($this->primary) {
$this->primary = clone $this->primary;
}
}
/**
* Get a primary phone number.
*/
public function getPrimary(): ?PhoneNumber
{
if ($this->isEmpty()) {
return null;
}
return $this->primary;
}
/**
* Get a list of all phone numbers.
*
* @return array<int, PhoneNumber>
*/
public function getList(): array
{
return $this->list;
}
/**
* Get a number of phone numbers.
*/
public function getCount(): int
{
return count($this->list);
}
/**
* Get a list of phone numbers w/o a primary.
*
* @return array<int, PhoneNumber>
*/
public function getSecondaryList(): array
{
$list = [];
foreach ($this->list as $item) {
if ($item === $this->primary) {
continue;
}
$list[] = $item;
}
return $list;
}
/**
* Get a list of phone numbers represented as strings.
*
* @return array<int, string>
*/
public function getNumberList(): array
{
$list = [];
foreach ($this->list as $item) {
$list[] = $item->getNumber();
}
return $list;
}
/**
* Get a phone number by number represented as a string.
*/
public function getByNumber(string $number): ?PhoneNumber
{
$index = $this->searchNumberInList($number);
if ($index === null) {
return null;
}
return $this->list[$index];
}
/**
* Whether an number is in the list.
*/
public function hasNumber(string $number): bool
{
return in_array($number, $this->getNumberList());
}
/**
* Clone with another primary phone number.
*/
public function withPrimary(PhoneNumber $phoneNumber): self
{
$list = $this->list;
$index = $this->searchNumberInList($phoneNumber->getNumber());
if ($index !== null) {
unset($list[$index]);
$list = array_values($list);
}
$newList = array_merge([$phoneNumber], $list);
return self::fromList($newList);
}
/**
* Clone with an added phone number list.
*
* @param array<int, PhoneNumber> $list
*/
public function withAddedList(array $list): self
{
$newList = $this->list;
foreach ($list as $item) {
$index = $this->searchNumberInList($item->getNumber());
if ($index !== null) {
$newList[$index] = $item;
continue;
}
$newList[] = $item;
}
return self::fromList($newList);
}
/**
* Clone with an added phone number.
*/
public function withAdded(PhoneNumber $phoneNumber): self
{
return $this->withAddedList([$phoneNumber]);
}
/**
* Clone with removed phone number.
*/
public function withRemoved(PhoneNumber $phoneNumber): self
{
return $this->withRemovedByNumber($phoneNumber->getNumber());
}
/**
* Clone with removed phone number passed by a number.
*/
public function withRemovedByNumber(string $number): self
{
$newList = $this->list;
$index = $this->searchNumberInList($number);
if ($index !== null) {
unset($newList[$index]);
$newList = array_values($newList);
}
return self::fromList($newList);
}
/**
* Create from a phone number list. A first item will be set as primary.
*
* @param array<int, PhoneNumber> $list
*/
public static function fromList(array $list): self
{
return new self($list);
}
/**
* Create empty.
*/
public static function fromNothing(): self
{
return new self([]);
}
private function searchNumberInList(string $number): ?int
{
foreach ($this->getNumberList() as $i => $item) {
if ($item === $number) {
return $i;
}
}
return null;
}
private function validateList(): void
{
$numberList = [];
foreach ($this->list as $item) {
if (!$item instanceof PhoneNumber) {
throw new RuntimeException("Bad item.");
}
if (in_array($item->getNumber(), $numberList)) {
throw new RuntimeException("Number list contains a duplicate.");
}
$numberList[] = strtolower($item->getNumber());
}
}
private function isEmpty(): bool
{
return count($this->list) === 0;
}
}