/**
* DISCOURAGED FUNCTIONS WITH MAGENTO REPLACEMENTS (Severity 8)
* These functions should be replaced with Magento Framework equivalents.
*/
export interface DiscouragedFunction {
replacement: string;
category: string;
reason: string;
}
export const DISCOURAGED_FUNCTIONS: Record<string, DiscouragedFunction> = {
// === FILE SYSTEM OPERATIONS ===
'fopen': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileOpen',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction for cloud/remote storage compatibility'
},
'fclose': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileClose',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fwrite': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileWrite',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fputs': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileWrite',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fread': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileRead',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fflush': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileFlush',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fgetcsv': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileGetCsv',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fputcsv': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::filePutCsv',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'ftell': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileTell',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'fseek': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileSeek',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'feof': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::endOfFile',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'flock': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileLock',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'file_exists': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isExists',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction for remote storage support'
},
'file_get_contents': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileGetContents',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'file_put_contents': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::filePutContents',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'readfile': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileRead',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'readline': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::fileReadLine',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
// === DIRECTORY OPERATIONS ===
'mkdir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::createDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'rmdir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::deleteDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'is_dir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'is_file': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isFile',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'is_readable': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isReadable',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'is_writable': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isWritable',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'is_writeable': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::isWritable',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
// === PATH OPERATIONS ===
'dirname': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::getParentDirectory',
category: 'path',
reason: 'Use Magento filesystem abstraction'
},
'realpath': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::getRealPath',
category: 'path',
reason: 'Use Magento filesystem abstraction'
},
'pathinfo': {
replacement: 'Magento\\Framework\\Filesystem\\Io\\File::getPathInfo',
category: 'path',
reason: 'Use Magento filesystem abstraction'
},
'glob': {
replacement: 'Magento\\Framework\\Filesystem\\Glob::glob',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
// === FILE MANIPULATION ===
'copy': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::copy',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'rename': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::rename',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'delete': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::deleteFile',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'unlink': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::deleteFile',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'touch': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::touch',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'chmod': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::changePermissions',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'symlink': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::symlink',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'stat': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::stat',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
'lstat': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::stat',
category: 'filesystem',
reason: 'Use Magento filesystem abstraction'
},
// === NETWORK ===
'fsockopen': {
replacement: 'Magento\\Framework\\Filesystem\\Driver\\Http::open',
category: 'network',
reason: 'Use Magento HTTP driver'
},
// === TRANSLATION ===
'gettext': {
replacement: 'Magento\\Framework\\Translate\\AdapterInterface::translate or __() function',
category: 'translation',
reason: 'Use Magento translation system'
},
'_': {
replacement: 'Use __() Magento translation function',
category: 'translation',
reason: 'Use Magento translation system'
},
'setlocale': {
replacement: 'Magento\\Framework\\Translate\\AdapterInterface::setLocale',
category: 'translation',
reason: 'Use Magento locale system'
},
// === HTML ESCAPING ===
'htmlspecialchars': {
replacement: '\\Magento\\Framework\\Escaper->escapeHtml()',
category: 'security',
reason: 'Use Magento Escaper for consistent XSS protection'
},
// === IMAGE OPERATIONS ===
'getimagesize': {
replacement: 'getimagesizefromstring() for remote storage compatibility',
category: 'image',
reason: 'Direct file access not compatible with remote storage'
},
// === TYPE CONVERSIONS ===
'intval': {
replacement: '(int) type casting',
category: 'type',
reason: 'Use PHP native type casting for clarity'
},
'strval': {
replacement: '(string) type casting',
category: 'type',
reason: 'Use PHP native type casting for clarity'
},
'is_null': {
replacement: '=== null strict comparison',
category: 'type',
reason: 'Use strict comparison for clarity'
},
'sizeof': {
replacement: 'count()',
category: 'type',
reason: 'sizeof is an alias, use count() for clarity'
},
'chop': {
replacement: 'rtrim()',
category: 'string',
reason: 'chop is an alias, use rtrim() for clarity'
},
// === DATE/TIME (PHP 8.1+ deprecations) ===
'strftime': {
replacement: 'IntlDateFormatter::format()',
category: 'date',
reason: 'Deprecated in PHP 8.1'
},
'gmstrftime': {
replacement: 'IntlDateFormatter::format()',
category: 'date',
reason: 'Deprecated in PHP 8.1'
},
'strptime': {
replacement: 'date_parse_from_format()',
category: 'date',
reason: 'Deprecated in PHP 8.1'
},
'date_sunrise': {
replacement: 'date_sun_info()',
category: 'date',
reason: 'Deprecated in PHP 8.1'
},
'date_sunset': {
replacement: 'date_sun_info()',
category: 'date',
reason: 'Deprecated in PHP 8.1'
},
// === DEBUGGING (never in production) ===
'var_dump': {
replacement: 'Use logging: $this->logger->debug() or Magento\\Framework\\Logger',
category: 'debug',
reason: 'Debug output should never be in production code'
},
'print_r': {
replacement: 'Use logging: $this->logger->debug()',
category: 'debug',
reason: 'Debug output should never be in production code'
},
'printf': {
replacement: 'Use sprintf() and proper output methods',
category: 'output',
reason: 'Direct output bypasses Magento response handling'
},
'vprintf': {
replacement: 'Use vsprintf() and proper output methods',
category: 'output',
reason: 'Direct output bypasses Magento response handling'
},
// === OUTPUT ===
'header': {
replacement: 'Use Magento\\Framework\\App\\Response\\Http',
category: 'output',
reason: 'Direct header manipulation bypasses Magento response'
},
'setcookie': {
replacement: 'Use Magento\\Framework\\Stdlib\\Cookie\\CookieMetadataFactory',
category: 'output',
reason: 'Use Magento cookie management'
},
'setrawcookie': {
replacement: 'Use Magento\\Framework\\Stdlib\\Cookie\\CookieMetadataFactory',
category: 'output',
reason: 'Use Magento cookie management'
},
// === SESSION ===
'session_start': {
replacement: 'Use Magento\\Framework\\Session\\SessionManagerInterface',
category: 'session',
reason: 'Use Magento session management'
},
'session_destroy': {
replacement: 'Use Magento\\Framework\\Session\\SessionManagerInterface::destroy()',
category: 'session',
reason: 'Use Magento session management'
},
'session_regenerate_id': {
replacement: 'Use Magento\\Framework\\Session\\SessionManagerInterface::regenerateId()',
category: 'session',
reason: 'Use Magento session management'
},
// === ENVIRONMENT ===
'getenv': {
replacement: 'Use Magento\\Framework\\App\\DeploymentConfig',
category: 'environment',
reason: 'Use Magento configuration system'
},
'putenv': {
replacement: 'Use Magento configuration system',
category: 'environment',
reason: 'Environment manipulation should be in configuration'
},
'ini_set': {
replacement: 'Configure in php.ini or Magento configuration',
category: 'environment',
reason: 'Runtime PHP configuration changes are discouraged'
},
'ini_alter': {
replacement: 'Configure in php.ini or Magento configuration',
category: 'environment',
reason: 'Runtime PHP configuration changes are discouraged'
},
'set_time_limit': {
replacement: 'Configure in php.ini or use async processing',
category: 'environment',
reason: 'Time limit changes indicate design issues'
},
// === ERROR HANDLING ===
'trigger_error': {
replacement: 'Throw appropriate exception or use Magento\\Framework\\Logger',
category: 'error',
reason: 'Use proper exception handling'
},
// === ENCODING ===
'base64_decode': {
replacement: 'Use with caution, validate input',
category: 'encoding',
reason: 'Can be used for obfuscation, ensure input is validated'
},
'extract': {
replacement: 'Access array elements directly',
category: 'security',
reason: 'Creates variables from array keys - potential security risk'
},
'parse_str': {
replacement: 'Use with second parameter to populate array',
category: 'security',
reason: 'Without second param, creates variables - security risk'
},
// === DANGEROUS FUNCTION CALLS ===
'call_user_func': {
replacement: 'Direct function/method call or closures',
category: 'security',
reason: 'Dynamic function call can be exploited, prefer direct calls'
},
'call_user_func_array': {
replacement: 'Direct function/method call with spread operator',
category: 'security',
reason: 'Dynamic function call can be exploited, prefer direct calls'
},
// === MAIL ===
'mail': {
replacement: 'Magento\\Framework\\Mail\\TransportInterface',
category: 'mail',
reason: 'Use Magento mail transport for proper email handling'
},
'mb_send_mail': {
replacement: 'Magento\\Framework\\Mail\\TransportInterface',
category: 'mail',
reason: 'Use Magento mail transport for proper email handling'
},
// === INFO DISCLOSURE ===
'highlight_file': {
replacement: 'Remove - information disclosure risk',
category: 'security',
reason: 'Exposes source code to users - information disclosure'
},
'show_source': {
replacement: 'Remove - information disclosure risk',
category: 'security',
reason: 'Alias for highlight_file - exposes source code'
},
'phpinfo': {
replacement: 'Remove - information disclosure risk',
category: 'security',
reason: 'Exposes server configuration - information disclosure'
},
// === FILE PARSING ===
'parse_ini_file': {
replacement: 'Use Magento\\Framework\\App\\DeploymentConfig for configuration',
category: 'filesystem',
reason: 'Direct file access - use Magento configuration system'
},
'parse_ini_string': {
replacement: 'Use Magento configuration readers',
category: 'filesystem',
reason: 'Use Magento configuration system instead'
},
// === PERFORMANCE ===
'sleep': {
replacement: 'Use async processing or queue system',
category: 'performance',
reason: 'Blocks execution - use Magento message queue for delayed processing'
},
'usleep': {
replacement: 'Use async processing or queue system',
category: 'performance',
reason: 'Blocks execution - use Magento message queue for delayed processing'
},
'time_nanosleep': {
replacement: 'Use async processing or queue system',
category: 'performance',
reason: 'Blocks execution'
},
// === FILE UPLOAD ===
'move_uploaded_file': {
replacement: 'Magento\\Framework\\File\\Uploader',
category: 'filesystem',
reason: 'Use Magento file uploader for proper validation and storage'
},
// === DIRECTORY ACCESS ===
'opendir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::readDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'scandir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::readDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'closedir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface methods',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
'readdir': {
replacement: 'Magento\\Framework\\Filesystem\\DriverInterface::readDirectory',
category: 'directory',
reason: 'Use Magento filesystem abstraction'
},
// === CURL (use Magento HTTP Client) ===
'curl_init': {
replacement: 'Magento\\Framework\\HTTP\\ClientInterface',
category: 'network',
reason: 'Use Magento HTTP client for proper request handling'
},
'curl_exec': {
replacement: 'Magento\\Framework\\HTTP\\ClientInterface',
category: 'network',
reason: 'Use Magento HTTP client'
},
'curl_setopt': {
replacement: 'Magento\\Framework\\HTTP\\ClientInterface',
category: 'network',
reason: 'Use Magento HTTP client'
},
'curl_close': {
replacement: 'Magento\\Framework\\HTTP\\ClientInterface',
category: 'network',
reason: 'Use Magento HTTP client'
},
'curl_multi_init': {
replacement: 'Magento\\Framework\\HTTP\\AsyncClientInterface',
category: 'network',
reason: 'Use Magento async HTTP client'
},
// === MYSQL (use Magento DB) ===
'mysql_connect': {
replacement: 'Magento\\Framework\\App\\ResourceConnection',
category: 'database',
reason: 'Removed in PHP 7.0 - use Magento resource connection'
},
'mysqli_connect': {
replacement: 'Magento\\Framework\\App\\ResourceConnection',
category: 'database',
reason: 'Use Magento resource connection'
},
'mysql_query': {
replacement: 'Magento repositories, collections, or query builder',
category: 'database',
reason: 'Removed in PHP 7.0 - use Magento DB abstraction'
},
'mysqli_query': {
replacement: 'Magento repositories, collections, or query builder',
category: 'database',
reason: 'Use Magento DB abstraction'
},
// === LIFECYCLE ===
'register_shutdown_function': {
replacement: 'Use Magento event/observer or plugin system',
category: 'lifecycle',
reason: 'Runtime lifecycle manipulation - use Magento patterns'
},
'set_include_path': {
replacement: 'Use Composer autoloading and Magento module registration',
category: 'environment',
reason: 'Path manipulation - use proper autoloading'
},
'set_error_handler': {
replacement: 'Use Magento\\Framework\\App\\ErrorHandler',
category: 'error',
reason: 'Use Magento error handling'
},
'set_exception_handler': {
replacement: 'Use Magento\\Framework\\App\\ExceptionHandler',
category: 'error',
reason: 'Use Magento exception handling'
},
// === OUTPUT CONTROL ===
'ob_start': {
replacement: 'Use Magento response object for output buffering',
category: 'output',
reason: 'Output buffering should be handled by Magento framework'
},
'ob_end_flush': {
replacement: 'Use Magento response object',
category: 'output',
reason: 'Output flushing should be handled by Magento framework'
},
'ob_get_contents': {
replacement: 'Use Magento response object',
category: 'output',
reason: 'Output buffering should be handled by Magento framework'
},
'echo': {
replacement: 'Use Magento response object or return from controller action',
category: 'output',
reason: 'Direct output bypasses Magento response handling'
},
'print': {
replacement: 'Use Magento response object or return from controller action',
category: 'output',
reason: 'Direct output bypasses Magento response handling'
},
'die': {
replacement: 'Throw appropriate exception',
category: 'lifecycle',
reason: 'Abruptly terminates execution - use proper exception handling'
},
'exit': {
replacement: 'Throw appropriate exception',
category: 'lifecycle',
reason: 'Abruptly terminates execution - use proper exception handling'
},
// === COMPACT/LIST ===
'compact': {
replacement: 'Build arrays explicitly: ["key" => $value]',
category: 'security',
reason: 'Creates array from variable names - implicit coupling, harder to trace'
},
};
/**
* Get replacement suggestion for a discouraged function
*/
export function getDiscouragedFunctionReplacement(functionName: string): DiscouragedFunction | null {
return DISCOURAGED_FUNCTIONS[functionName] || null;
}
/**
* Get all discouraged functions by category
*/
export function getDiscouragedFunctionsByCategory(category: string): Record<string, DiscouragedFunction> {
const result: Record<string, DiscouragedFunction> = {};
for (const [func, info] of Object.entries(DISCOURAGED_FUNCTIONS)) {
if (info.category === category) {
result[func] = info;
}
}
return result;
}