__( 'Newcomer', 'spacebay' ), 'min' => 0, ), array( 'name' => __( 'Member', 'spacebay' ), 'min' => 50, ), array( 'name' => __( 'Regular', 'spacebay' ), 'min' => 200, ), array( 'name' => __( 'Contributor', 'spacebay' ), 'min' => 500, ), array( 'name' => __( 'Veteran', 'spacebay' ), 'min' => 1000, ), array( 'name' => __( 'Legend', 'spacebay' ), 'min' => 2500, ), ); } /** * Cleans a ladder from the settings screen. * * Rows without a name are dropped, points are sorted from low to high, * the first level always starts at 0 and two levels never share a number. * * @param array $input Raw rows. * @return array[]|null Clean rows, or null when nothing usable is left. */ public static function sanitize( array $input ) { $rows = array(); $seen = array(); foreach ( array_slice( array_values( $input ), 0, self::MAX ) as $row ) { if ( ! is_array( $row ) ) { continue; } $name = mb_substr( trim( sanitize_text_field( (string) ( $row['name'] ?? '' ) ) ), 0, self::MAX_NAME ); $min = max( 0, min( 10000000, (int) ( $row['min'] ?? 0 ) ) ); if ( '' === $name || isset( $seen[ $min ] ) ) { continue; } $seen[ $min ] = true; $rows[] = array( 'name' => $name, 'min' => $min, ); } if ( ! $rows ) { return null; } usort( $rows, static function ( $a, $b ) { return $a['min'] - $b['min']; } ); $rows[0]['min'] = 0; return $rows; } /** * The ladder in use. * * @return array[] */ public static function all() { $levels = Settings::get( 'levels' ); $levels = is_array( $levels ) ? self::sanitize( $levels ) : null; return $levels ? $levels : self::defaults(); } /** * The level reached with a number of points, with progress to the next one. * * @param int $points Points. * @return array{number: int, name: string, min: int, next: array|null, progress: int} */ public static function for_points( $points ) { $points = (int) $points; $levels = self::all(); $index = 0; foreach ( $levels as $i => $level ) { if ( $points >= $level['min'] ) { $index = $i; } } $current = $levels[ $index ]; $next = $levels[ $index + 1 ] ?? null; $span = $next ? max( 1, $next['min'] - $current['min'] ) : 1; return array( 'number' => $index + 1, 'name' => $current['name'], 'min' => $current['min'], 'next' => $next ? array( 'name' => $next['name'], 'min' => $next['min'], 'remaining' => max( 0, $next['min'] - $points ), ) : null, 'progress' => $next ? max( 0, min( 100, (int) floor( 100 * ( $points - $current['min'] ) / $span ) ) ) : 100, ); } }