1515
1616namespace FloatPHP \Classes \Filesystem ;
1717
18+ /**
19+ * Advanced file manipulation.
20+ */
1821class File
1922{
2023 /**
@@ -24,7 +27,7 @@ class File
2427 * @param string $path
2528 * @return array
2629 */
27- public static function analyse ($ path ) : array
30+ public static function analyse (string $ path ) : array
2831 {
2932 return [
3033 'parent ' => self ::getParentDir ($ path ),
@@ -539,6 +542,26 @@ public static function w(string $path, $input = '', bool $append = false) : bool
539542 return (bool )@file_put_contents ($ path , $ input , $ flag );
540543 }
541544
545+ /**
546+ * Read file using stream.
547+ *
548+ * @access public
549+ * @param string $path
550+ * @return mixed
551+ */
552+ public static function read (string $ path ) : mixed
553+ {
554+ if ( self ::exists ($ path ) ) {
555+ if ( ($ handler = fopen ($ path , 'r ' )) ) {
556+ $ size = self ::getFileSize ($ path );
557+ $ content = fread ($ handler , $ size );
558+ fclose ($ handler );
559+ return $ content ;
560+ }
561+ }
562+ return false ;
563+ }
564+
542565 /**
543566 * Scan directory,
544567 * [ASC: 0],
@@ -635,8 +658,10 @@ public static function count(string $path = '.') : mixed
635658 /**
636659 * Parse ini file.
637660 *
638- * [Normal : 0]
639- *
661+ * [INI_SCANNER_NORMAL : 0].
662+ * [FILE_IGNORE_NEW_LINES : 2].
663+ * [FILE_SKIP_EMPTY_LINES : 4].
664+ *
640665 * @access public
641666 * @param string $path
642667 * @param bool $sections
@@ -645,11 +670,78 @@ public static function count(string $path = '.') : mixed
645670 */
646671 public static function parseIni (string $ path , bool $ sections = false , int $ mode = 0 ) : mixed
647672 {
648- return parse_ini_file (
649- Stringify::formatPath ($ path ),
650- $ sections ,
651- $ mode
652- );
673+ $ path = Stringify::formatPath ($ path );
674+
675+ if ( TypeCheck::isFunction ('parse_ini_file ' ) ) {
676+ return parse_ini_file ($ path , $ sections , $ mode );
677+ }
678+
679+ if ( !self ::exists ($ path ) || !self ::isReadable ($ path ) ) {
680+ throw new \RuntimeException ("File not found or not readable: {$ path }" );
681+ }
682+
683+ $ lines = file ($ path , 2 | 4 );
684+ $ data = [];
685+ $ section = null ;
686+
687+ foreach ($ lines as $ line ) {
688+ $ line = trim ($ line );
689+
690+ // Skip comments and empty lines
691+ if ( $ line === '' || $ line [0 ] === '; ' || $ line [0 ] === '# ' ) {
692+ continue ;
693+ }
694+
695+ // Remove trailing semicolon
696+ if ( substr ($ line , -1 ) === '; ' ) {
697+ $ line = substr ($ line , 0 , -1 );
698+ }
699+
700+ // Process sections
701+ if ( $ line [0 ] === '[ ' && substr ($ line , -1 ) === '] ' ) {
702+ if ( $ sections ) {
703+ $ section = substr ($ line , 1 , -1 );
704+ $ data [$ section ] = [];
705+ }
706+ continue ;
707+ }
708+
709+ // Process key-value pairs
710+ $ keyValue = explode ('= ' , $ line , 2 );
711+ if ( count ($ keyValue ) !== 2 ) {
712+ throw new \RuntimeException ("Invalid line in INI file: {$ line }" );
713+ }
714+
715+ [$ key , $ value ] = array_map ('trim ' , $ keyValue );
716+
717+ // Parse booleans, null, and numbers
718+ if ( strtolower ($ value ) === 'true ' ) {
719+ $ value = true ;
720+
721+ } elseif ( strtolower ($ value ) === 'false ' ) {
722+ $ value = false ;
723+
724+ } elseif ( strtolower ($ value ) === 'null ' ) {
725+ $ value = null ;
726+
727+ } elseif ( is_numeric ($ value ) ) {
728+ // Convert to int or float
729+ $ value = $ value + 0 ;
730+
731+ } else {
732+ // Remove quotes if present
733+ $ value = trim ($ value , '" \'' );
734+ }
735+
736+ if ( $ sections && $ section !== null ) {
737+ $ data [$ section ][$ key ] = $ value ;
738+
739+ } else {
740+ $ data [$ key ] = $ value ;
741+ }
742+ }
743+
744+ return $ data ;
653745 }
654746
655747 /**
0 commit comments