get( $cachekey ); if ( is_array( $cached ) ) { return $cached; } elseif ( $cached === 'NEGATIVE' ) { return false; } $code = wfEscapeShellArg( ":lang=$code" ); $ok = 0; $cmd = "fc-match $code"; $suggestion = wfShellExec( $cmd, $ok ); wfDebugLog( 'fcfont', "$cmd returned $ok" ); if ( $ok !== 0 ) { wfDebugLog( 'fcfont', "fc-match error output: $suggestion" ); $cache->set( $cachekey, 'NEGATIVE', $timeout ); return false; } $pattern = '/^(.*?): "(.*)" "(.*)"$/'; $matches = []; if ( !preg_match( $pattern, $suggestion, $matches ) ) { wfDebugLog( 'fcfont', "fc-match: return format not understood: $suggestion" ); $cache->set( $cachekey, 'NEGATIVE', $timeout ); return false; } list( , $file, $family, $type ) = $matches; wfDebugLog( 'fcfont', "fc-match: got $file: $family $type" ); $file = wfEscapeShellArg( $file ); $family = wfEscapeShellArg( $family ); $type = wfEscapeShellArg( $type ); $cmd = "fc-list $family $type $code file | grep $file"; $candidates = trim( wfShellExec( $cmd, $ok ) ); wfDebugLog( 'fcfont', "$cmd returned $ok" ); if ( $ok !== 0 ) { wfDebugLog( 'fcfont', "fc-list error output: $candidates" ); $cache->set( $cachekey, 'NEGATIVE', $timeout ); return false; } # trim spaces $files = array_map( 'trim', explode( "\n", $candidates ) ); $count = count( $files ); if ( !$count ) { wfDebugLog( 'fcfont', "fc-list got zero canditates: $candidates" ); } # remove the trailing ":" $chosen = substr( $files[0], 0, -1 ); wfDebugLog( 'fcfont', "fc-list got $count candidates; using $chosen" ); $data = [ 'family' => $family, 'type' => $type, 'file' => $chosen, ]; $cache->set( $cachekey, $data, $timeout ); return $data; } /** * @return BagOStuff */ protected static function getCache() { return wfGetCache( CACHE_ANYTHING ); } }