*/ public static function defaults(): array { return array( 'first_names' => array( 'Ada', 'Alan', 'Amara', 'Ben', 'Carla', 'Chen', 'Dara', 'Diego', 'Elena', 'Emeka', 'Farah', 'Finn', 'Grace', 'Hana', 'Hugo', 'Ines', 'Isaac', 'Jonah', 'Kai', 'Keira', 'Leo', 'Lina', 'Marco', 'Maya', 'Nadia', 'Noah', 'Olga', 'Omar', 'Priya', 'Quinn', 'Rosa', 'Sami', 'Sofia', 'Theo', 'Uma', 'Vera', 'Wes', 'Yara', 'Zane', 'Zoe' ), 'last_names' => array( 'Abbott', 'Baker', 'Castillo', 'Dunn', 'Ellis', 'Fischer', 'Garcia', 'Hale', 'Ito', 'Jensen', 'Khan', 'Larsen', 'Moreau', 'Nakamura', 'Okafor', 'Patel', 'Quint', 'Rossi', 'Silva', 'Tanaka', 'Umar', 'Varga', 'Walsh', 'Xu', 'Young', 'Zimmer' ), 'adjectives' => array( 'Classic', 'Cozy', 'Everyday', 'Handmade', 'Lightweight', 'Modern', 'Organic', 'Premium', 'Rustic', 'Sturdy', 'Soft', 'Travel', 'Vintage', 'Waterproof', 'Compact' ), 'nouns' => array( 'Backpack', 'Beanie', 'Blanket', 'Bottle', 'Candle', 'Cap', 'Mug', 'Notebook', 'Pillow', 'Scarf', 'Sneakers', 'Socks', 'Sweater', 'Tote bag', 'T-shirt', 'Wallet', 'Watch', 'Lamp', 'Planter', 'Apron' ), 'materials' => array( 'cotton', 'linen', 'wool', 'bamboo', 'recycled plastic', 'oak', 'ceramic', 'canvas', 'leather', 'steel' ), 'colours' => array( 'Black', 'White', 'Navy', 'Olive', 'Red', 'Sand', 'Grey', 'Teal', 'Mustard', 'Plum' ), 'sizes' => array( 'S', 'M', 'L', 'XL' ), 'categories' => array( 'Accessories', 'Home', 'Clothing', 'Outdoor', 'Kitchen', 'Office', 'Gifts', 'Bags' ), 'streets' => array( 'Maple Street', 'Oak Avenue', 'High Street', 'Station Road', 'Park Lane', 'Mill Road', 'Church Street', 'River Walk', 'Elm Close', 'Harbour View' ), 'cities' => array( 'Springfield', 'Riverton', 'Lakeside', 'Fairview', 'Brookfield', 'Hillcrest', 'Oakridge', 'Westbury', 'Kingsford', 'Ashford' ), 'companies' => array( 'Northwind', 'Bluebird Studio', 'Acorn & Co', 'Lumen Works', 'Harbor Goods', 'Pine Labs' ), 'reviews' => array( 'Exactly as described. Would buy again.', 'Good quality for the price.', 'Arrived quickly and well packed.', 'Nice, but a little smaller than I expected.', 'My second one. Still love it.', 'Does the job. Nothing special.', 'The colour is lovely in person.', 'Great gift, they were very happy with it.', 'Not what I hoped for, sadly.', 'Solid and well made.', ), ); } /** * Word banks after a filter: each bank the filter replaced must be a non-empty list of * non-empty strings (each cut to 100 characters), or the default bank is kept. * * @since 1.0.0 * @param mixed $filtered Output of the `apwc_test_data_words` filter. * @return array */ public static function banks( $filtered ): array { $banks = self::defaults(); if ( ! is_array( $filtered ) ) { return $banks; } foreach ( array_keys( $banks ) as $key ) { if ( ! isset( $filtered[ $key ] ) || ! is_array( $filtered[ $key ] ) ) { continue; } $words = array(); foreach ( $filtered[ $key ] as $word ) { if ( is_string( $word ) && '' !== trim( $word ) ) { $words[] = mb_substr( trim( $word ), 0, 100 ); } } if ( $words ) { $banks[ $key ] = array_values( array_unique( $words ) ); } } return $banks; } /** * Whether a domain is reserved for testing: ends in `.test`, `.example` or `.invalid` * (with a name before it), or is exactly example.com, example.net or example.org. * * @since 1.0.0 * @param mixed $domain Domain. * @return bool */ public static function is_reserved_domain( $domain ): bool { if ( ! is_string( $domain ) ) { return false; } $domain = strtolower( $domain ); if ( strlen( $domain ) > 253 || ! preg_match( '/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/D', $domain ) ) { return false; } if ( in_array( $domain, array( 'example.com', 'example.net', 'example.org' ), true ) ) { return true; } return (bool) preg_match( '/\.(?:test|example|invalid)$/D', $domain ); } /** * The email domain to use: the filtered one when it's reserved, else example.test. * * @since 1.0.0 * @param mixed $filtered Output of the `apwc_test_data_email_domain` filter. * @return string */ public static function domain( $filtered ): string { return self::is_reserved_domain( $filtered ) ? strtolower( (string) $filtered ) : self::DOMAIN; } /** * A fictional phone number: UK drama range for GB, else the US 555-01xx range. * * @since 1.0.0 * @param Random $random Generator. * @param string $country ISO country code. * @return string */ public static function phone( Random $random, string $country ): string { if ( 'GB' === strtoupper( $country ) ) { return sprintf( '07700 900%03d', $random->int( 0, 999 ) ); } return sprintf( '(%03d) 555-01%02d', $random->int( 201, 989 ), $random->int( 0, 99 ) ); } /** * Whether a phone number is in one of the fictional ranges phone() uses. * * @since 1.0.0 * @param string $phone Phone. * @return bool */ public static function is_fictional_phone( string $phone ): bool { return (bool) preg_match( '/^(?:07700 900\d{3}|\(\d{3}\) 555-01\d{2})$/D', $phone ); } /** * An IP address from TEST-NET-1 (192.0.2.1–254). * * @since 1.0.0 * @param Random $random Generator. * @return string */ public static function ip( Random $random ): string { return '192.0.2.' . $random->int( 1, 254 ); } /** * A plausible postcode for a country (never checked against real addresses). * * @since 1.0.0 * @param Random $random Generator. * @param string $country ISO country code. * @return string */ public static function postcode( Random $random, string $country ): string { switch ( strtoupper( $country ) ) { case 'GB': return sprintf( 'ZZ%d %dZZ', $random->int( 1, 99 ), $random->int( 1, 9 ) ); case 'CA': return sprintf( 'K%dA %dB%d', $random->int( 0, 9 ), $random->int( 0, 9 ), $random->int( 0, 9 ) ); case 'NL': return sprintf( '%04d AB', $random->int( 1000, 9999 ) ); default: return sprintf( '%05d', $random->int( 10000, 99999 ) ); } } /** * A slug-safe lowercase word for emails and usernames (ASCII letters only). * * @since 1.0.0 * @param string $word Word. * @return string */ public static function ascii( string $word ): string { $word = strtolower( (string) preg_replace( '/[^A-Za-z]+/', '', $word ) ); return '' === $word ? 'test' : $word; } }