array_key_exists( 'read_only', $stored ) ? (bool) $stored['read_only'] : true, 'disabled' => self::names( isset( $stored['disabled'] ) ? $stored['disabled'] : array() ), ); } /** * Save settings. Keys left out keep their current value. * * @param array $values `read_only` and/or `disabled`. * @return void */ public static function save( array $values ) { $settings = self::get(); if ( array_key_exists( 'read_only', $values ) ) { $settings['read_only'] = (bool) $values['read_only']; } if ( array_key_exists( 'disabled', $values ) ) { $settings['disabled'] = self::names( $values['disabled'] ); } update_option( self::OPTION, $settings, false ); } /** * Why an ability can't run: `disabled` (its switch is off), `read_only` (a write ability while * read-only mode is on), or '' when it can. * * @param string $switch The ability's switch: its family, or its own name. * @param bool $readonly Whether the ability only reads. * @return string */ public static function block_reason( $switch, $readonly ) { $settings = self::get(); if ( in_array( $switch, $settings['disabled'], true ) ) { return 'disabled'; } if ( $settings['read_only'] && ! $readonly ) { return 'read_only'; } return ''; } /** * Keep only well-formed switch names. * * @param mixed $raw Submitted list. * @return string[] */ private static function names( $raw ) { $names = array(); foreach ( (array) $raw as $name ) { if ( is_string( $name ) && 1 === preg_match( '#^[a-z0-9-]+/[a-z0-9-]+$#', $name ) ) { $names[] = $name; } } return array_values( array_unique( $names ) ); } }