Completed
Push — master ( 8a19bb...bfbfe3 )
by
unknown
18s queued 14s
created

DelegatingTicketStore   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 64
c 2
b 0
f 0
dl 0
loc 130
rs 10
wmc 23

4 Methods

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