DelegatingTicketStore::getTicket()   B
last analyzed

Complexity

Conditions 7
Paths 12

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 25
rs 8.8333
c 0
b 0
f 0
cc 7
nc 12
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\casserver\Cas\Ticket;
6
7
use Exception;
8
use InvalidArgumentException;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\Configuration;
11
use SimpleSAML\Logger;
12
use SimpleSAML\Module;
13
14
/**
15
 * Ticket store that delegates to other ticket stores.
16
 * Allows you to use multiple source for redundancy or allows a transition from one source to another.
17
 */
18
class DelegatingTicketStore extends TicketStore
19
{
20
    /**
21
     * @var string Delegate to 'all', 'first', or a named entry.
22
     */
23
    private string $delegateTo = 'all';
24
25
    /**
26
     * @var \SimpleSAML\Module\casserver\Cas\Ticket\TicketStore[]
27
     */
28
    private array $ticketStores = [];
29
30
    /**
31
     * @var \SimpleSAML\Module\casserver\Cas\Ticket\TicketStore
32
     */
33
    private TicketStore $primaryDelegate;
34
35
36
    /**
37
     * @param \SimpleSAML\Configuration $casConfig The cas configuration.
38
     */
39
    public function __construct(Configuration $casConfig)
40
    {
41
        $config = $casConfig->getConfigItem('ticketstore');
42
        $this->delegateTo = $config->getOptionalString('delegateTo', 'all');
43
        foreach ($config->getArray('ticketStores') as $name => $storeArray) {
44
            // TicketStore expects the store config to be in a specific item
45
            $storeConfig = Configuration::loadFromArray(['ticketstore' => $storeArray]);
46
            $class = $storeConfig->getConfigItem('ticketstore')->getString('class');
47
            $ticketStoreClass = Module::resolveClass($class, 'Cas\Ticket');
48
            try {
49
                /**
50
                 * @var \SimpleSAML\Module\casserver\Cas\Ticket\TicketStore $ticketStore
51
                 */
52
                $ticketStore = new $ticketStoreClass($storeConfig);
53
                $this->ticketStores[$name] = $ticketStore;
54
            } catch (Exception $e) {
55
                Logger::error("Unable to create ticket store '$name'. Error " . $e->getMessage());
56
            }
57
        }
58
        Assert::notEmpty($this->ticketStores, "'ticketStores' must be defined.");
59
        $this->ticketStores = $this->ticketStores;
60
61
        if ($this->delegateTo === 'first') {
62
            $this->primaryDelegate = reset($this->ticketStores);
63
        } elseif ($this->delegateTo !== 'all') {
64
            if (array_key_exists($this->delegateTo, $this->ticketStores)) {
65
                $this->primaryDelegate = $this->ticketStores[$this->delegateTo];
66
            } else {
67
                throw new InvalidArgumentException("No ticket store called '" . $this->delegateTo . "'");
68
            }
69
        }
70
    }
71
72
    /**
73
     * Get the ticket, searching one or all of the delegates
74
     * @param string $ticketId The ticket to find
75
     * @return array|null The ticket or null if none found
76
     * @throws \Exception from any delegate stores ONLY if no delegates worked
77
     */
78
    public function getTicket(string $ticketId): ?array
79
    {
80
        if ($this->delegateTo === 'all') {
81
            $ticket = null;
82
            $rethrowException = null;
83
            foreach ($this->ticketStores as $name => $store) {
84
                try {
85
                    $ticket = $store->getTicket($ticketId);
86
                    $rethrowException = false; // no need to rethrow, at least one store worked
87
                } catch (Exception $e) {
88
                    if ($rethrowException === null) {
89
                        $rethrowException = $e;
90
                    }
91
                    Logger::error("Unable to read tickets from '$name'. Trying next store. Error " . $e->getMessage());
92
                }
93
                if ($ticket) {
94
                    return $ticket;
95
                }
96
            }
97
            if ($rethrowException) {
98
                throw $rethrowException;
99
            }
100
            return $ticket;
101
        } else {
102
            return $this->primaryDelegate->getTicket($ticketId);
103
        }
104
    }
105
106
    /**
107
     * @param array $ticket Ticket to add
108
     * @throws \Exception from any delegate stores ONLY if no delegates worked
109
     */
110
    public function addTicket(array $ticket): void
111
    {
112
        if ($this->delegateTo === 'all') {
113
            $rethrowException = null;
114
            foreach ($this->ticketStores as $name => $store) {
115
                try {
116
                    $store->addTicket($ticket);
117
                    $rethrowException = false; // no need to rethrow, at least one store worked
118
                } catch (Exception $e) {
119
                    if ($rethrowException === null) {
120
                        $rethrowException = $e;
121
                    }
122
                    Logger::error("Unable to add ticket to '$name'. Continue to next store. Error" . $e->getMessage());
123
                }
124
            }
125
            if ($rethrowException) {
126
                throw $rethrowException;
127
            }
128
        } else {
129
            $this->primaryDelegate->addTicket($ticket);
130
        }
131
    }
132
133
134
    /**
135
     * @param string $ticketId Ticket to delete
136
     */
137
    public function deleteTicket(string $ticketId): void
138
    {
139
        if ($this->delegateTo === 'all') {
140
            foreach ($this->ticketStores as $name => $store) {
141
                try {
142
                    $store->deleteTicket($ticketId);
143
                } catch (Exception $e) {
144
                    Logger::error("Unable to delete ticket from '$name'. Trying next store. Error" . $e->getMessage());
145
                }
146
            }
147
        } else {
148
            $this->primaryDelegate->deleteTicket($ticketId);
149
        }
150
    }
151
}
152