Merge pull request #15818 from colemanw/fields
[civicrm-core.git] / Civi / Core / Lock / LockManager.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11 namespace Civi\Core\Lock;
12
13 use Civi\Core\Resolver;
14
15 /**
16 * Class LockManager
17 * @package Civi\Core\Lock
18 *
19 * The lock-manager allows one to define the lock policy -- i.e. given a
20 * specific lock, how does one acquire the lock?
21 */
22 class LockManager {
23
24 private $rules = [];
25
26 /**
27 * @param string $name
28 * Symbolic name for the lock. Names generally look like
29 * "worker.mailing.EmailProcessor" ("{category}.{component}.{AdhocName}").
30 *
31 * Categories: worker|data|cache|...
32 * Component: core|mailing|member|contribute|...
33 * @return LockInterface
34 * @throws \CRM_Core_Exception
35 */
36 public function create($name) {
37 $factory = $this->getFactory($name);
38 if ($factory) {
39 /** @var LockInterface $lock */
40 $lock = call_user_func_array($factory, [$name]);
41 return $lock;
42 }
43 else {
44 throw new \CRM_Core_Exception("Lock \"$name\" does not match any rules. Use register() to add more rules.");
45 }
46 }
47
48 /**
49 * Create and attempt to acquire a lock.
50 *
51 * Note: Be sure to check $lock->isAcquired() to determine whether
52 * acquisition was successful.
53 *
54 * @param string $name
55 * Symbolic name for the lock. Names generally look like
56 * "worker.mailing.EmailProcessor" ("{category}.{component}.{AdhocName}").
57 *
58 * Categories: worker|data|cache|...
59 * Component: core|mailing|member|contribute|...
60 * @param int|null $timeout
61 * The number of seconds to wait to get the lock.
62 * For a default value, use NULL.
63 * @return LockInterface
64 * @throws \CRM_Core_Exception
65 */
66 public function acquire($name, $timeout = NULL) {
67 $lock = $this->create($name);
68 $lock->acquire($timeout);
69 return $lock;
70 }
71
72 /**
73 * @param string $name
74 * Symbolic name for the lock.
75 * @return callable|NULL
76 */
77 public function getFactory($name) {
78 foreach ($this->rules as $rule) {
79 if (preg_match($rule['pattern'], $name)) {
80 return Resolver::singleton()->get($rule['factory']);
81 }
82 }
83 return NULL;
84 }
85
86 /**
87 * Register the lock-factory to use for specific lock-names.
88 *
89 * @param string $pattern
90 * A regex to match against the lock name.
91 * @param string|array $factory
92 * A callback. The callback should accept a $name parameter.
93 * Callbacks will be located using the resolver.
94 * @return LockManager
95 * @see Resolver
96 */
97 public function register($pattern, $factory) {
98 $this->rules[] = [
99 'pattern' => $pattern,
100 'factory' => $factory,
101 ];
102 return $this;
103 }
104
105 }