1212 */
1313class MacDevice
1414{
15+ const CPU_INTEL = 'intel ' ;
16+ const CPU_APPLE = 'apple ' ;
17+
1518 use ShellTrait;
1619
1720 /** @var int */
@@ -24,6 +27,8 @@ class MacDevice
2427 protected $ _OS ;
2528 /** @var MacNetworkSubsystem */
2629 protected $ _Network ;
30+ /** @var string[] */
31+ protected $ _SPHardwareDataType ;
2732
2833 /**
2934 * @return MacNetworkSubsystem
@@ -66,6 +71,29 @@ public function getCpuCores()
6671 return $ this ->_cores ;
6772 }
6873
74+ /**
75+ * @return string|null
76+ */
77+ public function getCpuType ()
78+ {
79+ $ cmd = '/usr/bin/uname -m ' ;
80+ if ($ cpu = $ this ->getShellExec ($ cmd ))
81+ {
82+ switch ($ cpu )
83+ {
84+ case 'x86_64 ' :
85+ case 'i386 ' :
86+ return self ::CPU_INTEL ;
87+ case 'arm64 ' :
88+ return self ::CPU_APPLE ;
89+ default :
90+ break ;
91+ }
92+ }
93+
94+ return null ;
95+ }
96+
6997 /**
7098 * Returns free disk space in Gibibyte (1024), as returned by the DF binary.
7199 *
@@ -78,6 +106,54 @@ public function getFreeDiskSpace()
78106 return $ this ->getShellExec ("/bin/df -g / | /usr/bin/awk '(NR == 2){print $4}' " );
79107 }
80108
109+ /**
110+ * @return string|null
111+ */
112+ public function getModelIdentifier ()
113+ {
114+ return $ this ->getSpHardwareDataType ('model_identifier ' );
115+ }
116+
117+ /**
118+ * @return string|null
119+ */
120+ public function getModelName ()
121+ {
122+ return $ this ->getSpHardwareDataType ('model_name ' );
123+ }
124+
125+ /**
126+ * @return string|null
127+ */
128+ public function getProcessorName ()
129+ {
130+ return $ this ->getSpHardwareDataType ('processor_name ' );
131+ }
132+
133+ /**
134+ * @return string|null
135+ */
136+ public function getProcessorSpeed ()
137+ {
138+ return $ this ->getSpHardwareDataType ('processor_speed ' );
139+ }
140+
141+ /**
142+ * @return string|null
143+ */
144+ public function getSerialNumber ()
145+ {
146+ return $ this ->getSpHardwareDataType ('serial_number_system ' );
147+ }
148+
149+ /**
150+ * @return bool
151+ */
152+ public function isAppleChip ()
153+ {
154+ return self ::CPU_APPLE == $ this ->getCpuType ();
155+ }
156+
81157 /**
82158 * Determines if the system is running off of battery power, or AC power.
83159 *
@@ -103,6 +179,14 @@ public function isDisplaySleepPrevented()
103179 return !empty ($ a );
104180 }
105181
182+ /**
183+ * @return bool
184+ */
185+ public function isIntelChip ()
186+ {
187+ return self ::CPU_INTEL == $ this ->getCpuType ();
188+ }
189+
106190 /**
107191 * Determines if running on a Mac.
108192 *
@@ -113,6 +197,14 @@ public function isMac()
113197 return PHP_OS === 'Darwin ' ;
114198 }
115199
200+ /**
201+ * @return bool
202+ */
203+ public function isMacBook ()
204+ {
205+ return false !== strpos ($ this ->getModelName (), 'MacBook ' );
206+ }
207+
116208 /**
117209 * Determines if the Mac has a T2 security chip.
118210 *
@@ -153,4 +245,41 @@ public function isSecureBoot()
153245
154246 return $ this ->_secureBoot ;
155247 }
248+
249+ /**
250+ * @param string|null $key
251+ *
252+ * @return string[]|string
253+ */
254+ protected function getSpHardwareDataType ($ key = null )
255+ {
256+ if (is_null ($ this ->_SPHardwareDataType ))
257+ {
258+ if ($ result = $ this ->getShellExec ('system_profiler SPHardwareDataType | grep ": " ' ))
259+ {
260+ if (preg_match_all ('#\s*([^:]+):\s(.*)# ' , $ result , $ matches , PREG_SET_ORDER ))
261+ {
262+ foreach ($ matches as $ match )
263+ {
264+ $ key = !empty ($ match [1 ]) ? preg_replace ('~(?<= \\w)([A-Z])~u ' , '_$1 ' , $ match [1 ]) : null ;
265+ $ val = !empty ($ match [2 ]) ? $ match [2 ] : null ;
266+
267+ if ($ key && $ val )
268+ {
269+ $ this ->_SPHardwareDataType [$ key ] = $ val ;
270+ }
271+ }
272+ }
273+ }
274+ }
275+
276+ if ($ key )
277+ {
278+ return !empty ($ this ->_SPHardwareDataType [$ key ]) ? $ this ->_SPHardwareDataType [$ key ] : null ;
279+ }
280+ else
281+ {
282+ return $ this ->_SPHardwareDataType ;
283+ }
284+ }
156285}
0 commit comments