1<?php 2 3declare(strict_types=1); 4 5namespace PhpMyAdmin; 6 7use function count; 8use function explode; 9use function sprintf; 10 11final class ReplicationInfo 12{ 13 /** @var string[] */ 14 public $primaryVariables = [ 15 'File', 16 'Position', 17 'Binlog_Do_DB', 18 'Binlog_Ignore_DB', 19 ]; 20 21 /** @var string[] */ 22 public $replicaVariables = [ 23 'Slave_IO_State', 24 'Master_Host', 25 'Master_User', 26 'Master_Port', 27 'Connect_Retry', 28 'Master_Log_File', 29 'Read_Master_Log_Pos', 30 'Relay_Log_File', 31 'Relay_Log_Pos', 32 'Relay_Master_Log_File', 33 'Slave_IO_Running', 34 'Slave_SQL_Running', 35 'Replicate_Do_DB', 36 'Replicate_Ignore_DB', 37 'Replicate_Do_Table', 38 'Replicate_Ignore_Table', 39 'Replicate_Wild_Do_Table', 40 'Replicate_Wild_Ignore_Table', 41 'Last_Errno', 42 'Last_Error', 43 'Skip_Counter', 44 'Exec_Master_Log_Pos', 45 'Relay_Log_Space', 46 'Until_Condition', 47 'Until_Log_File', 48 'Until_Log_Pos', 49 'Master_SSL_Allowed', 50 'Master_SSL_CA_File', 51 'Master_SSL_CA_Path', 52 'Master_SSL_Cert', 53 'Master_SSL_Cipher', 54 'Master_SSL_Key', 55 'Seconds_Behind_Master', 56 ]; 57 58 /** @var array */ 59 private $primaryStatus; 60 61 /** @var array */ 62 private $replicaStatus; 63 64 /** @var array */ 65 private $multiPrimaryStatus; 66 67 /** @var array */ 68 private $primaryInfo; 69 70 /** @var array */ 71 private $replicaInfo; 72 73 /** @var DatabaseInterface */ 74 private $dbi; 75 76 public function __construct(DatabaseInterface $dbi) 77 { 78 $this->dbi = $dbi; 79 } 80 81 public function load(?string $connection = null): void 82 { 83 global $url_params; 84 85 $this->setPrimaryStatus(); 86 87 if (! empty($connection)) { 88 $this->setMultiPrimaryStatus(); 89 90 if ($this->multiPrimaryStatus) { 91 $this->setDefaultPrimaryConnection($connection); 92 $url_params['master_connection'] = $connection; 93 } 94 } 95 96 $this->setReplicaStatus(); 97 $this->setPrimaryInfo(); 98 $this->setReplicaInfo(); 99 } 100 101 private function setPrimaryStatus(): void 102 { 103 $this->primaryStatus = $this->dbi->fetchResult('SHOW MASTER STATUS'); 104 } 105 106 /** 107 * @return array 108 */ 109 public function getPrimaryStatus() 110 { 111 return $this->primaryStatus; 112 } 113 114 private function setReplicaStatus(): void 115 { 116 $this->replicaStatus = $this->dbi->fetchResult('SHOW SLAVE STATUS'); 117 } 118 119 /** 120 * @return array 121 */ 122 public function getReplicaStatus() 123 { 124 return $this->replicaStatus; 125 } 126 127 private function setMultiPrimaryStatus(): void 128 { 129 $this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL SLAVES STATUS'); 130 } 131 132 private function setDefaultPrimaryConnection(string $connection): void 133 { 134 $this->dbi->query(sprintf('SET @@default_master_connection = \'%s\'', $this->dbi->escapeString($connection))); 135 } 136 137 private static function fill(array $status, string $key): array 138 { 139 if (empty($status[0][$key])) { 140 return []; 141 } 142 143 return explode(',', $status[0][$key]); 144 } 145 146 private function setPrimaryInfo(): void 147 { 148 $this->primaryInfo = ['status' => false]; 149 150 if (count($this->primaryStatus) > 0) { 151 $this->primaryInfo['status'] = true; 152 } 153 154 if (! $this->primaryInfo['status']) { 155 return; 156 } 157 158 $this->primaryInfo['Do_DB'] = self::fill($this->primaryStatus, 'Binlog_Do_DB'); 159 $this->primaryInfo['Ignore_DB'] = self::fill($this->primaryStatus, 'Binlog_Ignore_DB'); 160 } 161 162 /** 163 * @return array 164 */ 165 public function getPrimaryInfo(): array 166 { 167 return $this->primaryInfo; 168 } 169 170 private function setReplicaInfo(): void 171 { 172 $this->replicaInfo = ['status' => false]; 173 174 if (count($this->replicaStatus) > 0) { 175 $this->replicaInfo['status'] = true; 176 } 177 178 if (! $this->replicaInfo['status']) { 179 return; 180 } 181 182 $this->replicaInfo['Do_DB'] = self::fill($this->replicaStatus, 'Replicate_Do_DB'); 183 $this->replicaInfo['Ignore_DB'] = self::fill($this->replicaStatus, 'Replicate_Ignore_DB'); 184 $this->replicaInfo['Do_Table'] = self::fill($this->replicaStatus, 'Replicate_Do_Table'); 185 $this->replicaInfo['Ignore_Table'] = self::fill($this->replicaStatus, 'Replicate_Ignore_Table'); 186 $this->replicaInfo['Wild_Do_Table'] = self::fill($this->replicaStatus, 'Replicate_Wild_Do_Table'); 187 $this->replicaInfo['Wild_Ignore_Table'] = self::fill($this->replicaStatus, 'Replicate_Wild_Ignore_Table'); 188 } 189 190 /** 191 * @return array 192 */ 193 public function getReplicaInfo(): array 194 { 195 return $this->replicaInfo; 196 } 197} 198