@@ -2355,109 +2355,153 @@ public function getCondition($stackPtr, $type)
2355
2355
2356
2356
/**
2357
2357
* Returns the name of the class that the specified class extends.
2358
- * (works for classes, anonymous classes and interfaces)
2358
+ *
2359
+ * Works for classes, anonymous classes and interfaces, though it is
2360
+ * strongly recommended to use the findExtendedInterfaceNames() method
2361
+ * to examine interfaces as they can extend multiple parent interfaces.
2359
2362
*
2360
2363
* Returns FALSE on error or if there is no extended class name.
2361
2364
*
2362
- * @param int $stackPtr The stack position of the class.
2365
+ * @param int $stackPtr The stack position of the class keyword .
2363
2366
*
2364
2367
* @return string|false
2365
2368
*/
2366
2369
public function findExtendedClassName ($ stackPtr )
2367
2370
{
2368
- // Check for the existence of the token.
2369
- if (isset ($ this ->tokens [$ stackPtr ]) === false ) {
2370
- return false ;
2371
- }
2371
+ $ validStructures = [
2372
+ T_CLASS => true ,
2373
+ T_ANON_CLASS => true ,
2374
+ T_INTERFACE => true ,
2375
+ ];
2372
2376
2373
- if ($ this ->tokens [$ stackPtr ]['code ' ] !== T_CLASS
2374
- && $ this ->tokens [$ stackPtr ]['code ' ] !== T_ANON_CLASS
2375
- && $ this ->tokens [$ stackPtr ]['code ' ] !== T_INTERFACE
2376
- ) {
2377
- return false ;
2378
- }
2377
+ $ classes = $ this ->examineObjectDeclarationSignature ($ stackPtr , $ validStructures , T_EXTENDS );
2379
2378
2380
- if (isset ( $ this -> tokens [ $ stackPtr ][ ' scope_opener ' ] ) === false ) {
2379
+ if (empty ( $ classes ) === true ) {
2381
2380
return false ;
2382
2381
}
2383
2382
2384
- $ classOpenerIndex = $ this ->tokens [$ stackPtr ]['scope_opener ' ];
2385
- $ extendsIndex = $ this ->findNext (T_EXTENDS , $ stackPtr , $ classOpenerIndex );
2386
- if (false === $ extendsIndex ) {
2387
- return false ;
2388
- }
2383
+ // Classes can only extend one parent class.
2384
+ return $ classes [0 ];
2389
2385
2390
- $ find = [
2391
- T_NS_SEPARATOR ,
2392
- T_STRING ,
2393
- T_WHITESPACE ,
2394
- ];
2386
+ }//end findExtendedClassName()
2395
2387
2396
- $ end = $ this ->findNext ($ find , ($ extendsIndex + 1 ), ($ classOpenerIndex + 1 ), true );
2397
- $ name = $ this ->getTokensAsString (($ extendsIndex + 1 ), ($ end - $ extendsIndex - 1 ));
2398
- $ name = trim ($ name );
2399
2388
2400
- if ($ name === '' ) {
2389
+ /**
2390
+ * Returns the names of the interfaces that the specified interface extends.
2391
+ *
2392
+ * Returns FALSE on error or if there is no extended interface name.
2393
+ *
2394
+ * @param int $stackPtr The stack position of the interface keyword.
2395
+ *
2396
+ * @return array|false
2397
+ */
2398
+ public function findExtendedInterfaceNames ($ stackPtr )
2399
+ {
2400
+ $ validStructures = [T_INTERFACE => true ];
2401
+
2402
+ $ interfaces = $ this ->examineObjectDeclarationSignature ($ stackPtr , $ validStructures , T_EXTENDS );
2403
+
2404
+ if (empty ($ interfaces ) === true ) {
2401
2405
return false ;
2402
2406
}
2403
2407
2404
- return $ name ;
2408
+ return $ interfaces ;
2405
2409
2406
- }//end findExtendedClassName ()
2410
+ }//end findExtendedInterfaceNames ()
2407
2411
2408
2412
2409
2413
/**
2410
2414
* Returns the names of the interfaces that the specified class implements.
2411
2415
*
2412
2416
* Returns FALSE on error or if there are no implemented interface names.
2413
2417
*
2414
- * @param int $stackPtr The stack position of the class.
2418
+ * @param int $stackPtr The stack position of the class keyword .
2415
2419
*
2416
2420
* @return array|false
2417
2421
*/
2418
2422
public function findImplementedInterfaceNames ($ stackPtr )
2423
+ {
2424
+ $ validStructures = [
2425
+ T_CLASS => true ,
2426
+ T_ANON_CLASS => true ,
2427
+ ];
2428
+
2429
+ $ interfaces = $ this ->examineObjectDeclarationSignature ($ stackPtr , $ validStructures , T_IMPLEMENTS );
2430
+
2431
+ if (empty ($ interfaces ) === true ) {
2432
+ return false ;
2433
+ }
2434
+
2435
+ return $ interfaces ;
2436
+
2437
+ }//end findImplementedInterfaceNames()
2438
+
2439
+
2440
+ /**
2441
+ * Returns the names of the extended classes or interfaces or the implemented
2442
+ * interfaces that the specific class/interface declaration extends/implements.
2443
+ *
2444
+ * Returns FALSE on error or if the object does not extend/implement another
2445
+ * object.
2446
+ *
2447
+ * @param int $stackPtr The stack position of the class/interface keyword.
2448
+ * @param array $OOTypes Array of accepted token types.
2449
+ * Array format <token constant> => true.
2450
+ * @param int $keyword The keyword to examine. Either `T_EXTENDS` or `T_IMPLEMENTS`.
2451
+ *
2452
+ * @return array|false
2453
+ */
2454
+ private function examineObjectDeclarationSignature ($ stackPtr , $ OOTypes , $ keyword )
2419
2455
{
2420
2456
// Check for the existence of the token.
2421
2457
if (isset ($ this ->tokens [$ stackPtr ]) === false ) {
2422
2458
return false ;
2423
2459
}
2424
2460
2425
- if ($ this ->tokens [$ stackPtr ]['code ' ] !== T_CLASS
2426
- && $ this ->tokens [$ stackPtr ]['code ' ] !== T_ANON_CLASS
2427
- ) {
2461
+ if (isset ($ OOTypes [$ this ->tokens [$ stackPtr ]['code ' ]]) === false ) {
2428
2462
return false ;
2429
2463
}
2430
2464
2431
- if (isset ($ this ->tokens [$ stackPtr ]['scope_closer ' ]) === false ) {
2465
+ if (isset ($ this ->tokens [$ stackPtr ]['scope_opener ' ]) === false ) {
2432
2466
return false ;
2433
2467
}
2434
2468
2435
- $ classOpenerIndex = $ this ->tokens [$ stackPtr ]['scope_opener ' ];
2436
- $ implementsIndex = $ this ->findNext (T_IMPLEMENTS , $ stackPtr , $ classOpenerIndex );
2437
- if ($ implementsIndex === false ) {
2469
+ $ openerIndex = $ this ->tokens [$ stackPtr ]['scope_opener ' ];
2470
+ $ keywordIndex = $ this ->findNext ($ keyword , ( $ stackPtr + 1 ) , $ openerIndex );
2471
+ if ($ keywordIndex === false ) {
2438
2472
return false ;
2439
2473
}
2440
2474
2441
- $ find = [
2442
- T_NS_SEPARATOR ,
2443
- T_STRING ,
2444
- T_WHITESPACE ,
2445
- T_COMMA ,
2446
- ];
2475
+ $ find = Util \Tokens::$ emptyTokens ;
2476
+ $ find [] = T_NS_SEPARATOR ;
2477
+ $ find [] = T_STRING ;
2478
+ $ find [] = T_COMMA ;
2447
2479
2448
- $ end = $ this ->findNext ($ find , ($ implementsIndex + 1 ), ($ classOpenerIndex + 1 ), true );
2449
- $ name = $ this ->getTokensAsString (($ implementsIndex + 1 ), ($ end - $ implementsIndex - 1 ));
2450
- $ name = trim ($ name );
2480
+ $ end = $ this ->findNext ($ find , ($ keywordIndex + 1 ), ($ openerIndex + 1 ), true );
2481
+ $ names = [];
2482
+ $ name = '' ;
2483
+ for ($ i = ($ keywordIndex + 1 ); $ i < $ end ; $ i ++) {
2484
+ if (isset (Util \Tokens::$ emptyTokens [$ this ->tokens [$ i ]['code ' ]]) === true ) {
2485
+ continue ;
2486
+ }
2451
2487
2452
- if ($ name === '' ) {
2453
- return false ;
2454
- } else {
2455
- $ names = explode (', ' , $ name );
2456
- $ names = array_map ('trim ' , $ names );
2457
- return $ names ;
2488
+ if ($ this ->tokens [$ i ]['code ' ] === T_COMMA && $ name !== '' ) {
2489
+ $ names [] = $ name ;
2490
+ $ name = '' ;
2491
+ continue ;
2492
+ }
2493
+
2494
+ $ name .= $ this ->tokens [$ i ]['content ' ];
2458
2495
}
2459
2496
2460
- }//end findImplementedInterfaceNames()
2497
+ // Add the last name.
2498
+ if ($ name !== '' ) {
2499
+ $ names [] = $ name ;
2500
+ }
2501
+
2502
+ return $ names ;
2503
+
2504
+ }//end examineObjectDeclarationSignature()
2461
2505
2462
2506
2463
2507
}//end class
0 commit comments