Search code examples
phparraysjsonloopsfile-put-contents

create a y-m-d.json file in the respective directory (year/month) by iterating multidimensional array


try to create or update a json file based on the processed data.

first I arrange the contents using assamble() and create a multidimensional array:

$logfile_accepted_array = [
    "AAAA 2022 12 23 21:37:56 dc:16:b2:4c:d2:e6",
    "BBB 2023 01 12 02:08:23 f0:8a:76:16:57:e8",
    "BBB 2023 02 19 17:34:33 a0:c9:a0:b6:79:3c",
    "AAAA 2023 02 23 12:21:09 f0:8a:76:16:57:e8",
    "AAAA 2023 02 23 18:15:10 f0:8a:76:16:57:e8",
    "CCCCC 2023 03 19 17:07:26 f0:8a:76:16:57:e8",
    "QQQ 2023 04 01 00:00:03 a0:c9:a0:b6:79:3c"
];

// Make directory and subdirectories ...
function dirMaker($directory, $sub_directory, $sub_sub_directory)
{
    if (!is_dir($directory . $sub_directory . $sub_sub_directory)) {
        mkdir(
            $directory . $sub_directory . $sub_sub_directory,
            0777,
            true
            // If true, then any parent directories 
            // to the directory specified will also be created, 
            // with the same permissions.
        );
    }
}

$root = 'archive/';

assemble data

function assemble($logfile_accepted_array)
{
    global $dailyData;

    # Get the colors for the zone 
    $getColors = file_get_contents('zones.json');
    $zoneColor = json_decode($getColors, true);
    // Group rows of data by column value then store nested data, first and last occurrences, and counts within each group
    foreach ($logfile_accepted_array as $row) {
        [$group, $date_year, $date_month_numeric, $day_digits, $time, $id] = explode(' ', $row);
        $result[$date_year][$date_month_numeric][$day_digits][$group]['user'][$id][] = $time;
    }

    $dailyData = $result;
}
assemble($logfile_accepted_array);

result

array (
  2022 => 
  array (
    12 => 
    array (
      23 => 
      array (
        'AAAA' => 
        array (
          'user' => 
          array (
            'dc:16:b2:4c:d2:e6' => 
            array (
              0 => '21:37:56',
            ),
          ),
        ),
      ),
    ),
  ),
  2023 => 
  array (
    '01' => 
    array (
      12 => 
      array (
        'BBB' => 
        array (
          'user' => 
          array (
            'f0:8a:76:16:57:e8' => 
            array (
              0 => '02:08:23',
            ),
          ),
        ),
      ),
    ),
/...

And now comes the big challenge:

  • create a y-m-d.json file in the respective directory (year/month) by iterating multidimensional array

In json files the year, month and day should not be omitted. But put in the correct year/month directory with which json filenames (y-m-d.json) are written.

function archiveJSON($logfile_accepted_array, $root, $dailyData)
{
    foreach ($logfile_accepted_array as $year_group) {
        [$group, $date_year, $date_month_numeric, $day_digits, $time, $id] = explode(' ', $year_group);
        $yearDir[$group][] = $date_year;
        $monthDir[$group][] = $date_month_numeric;
        $dayDir[$group][] = $day_digits;
        $user_id[$group][] = $id;
        $loged_time[$group][] = $time;

        dirMaker($root, $date_year . '/', $date_month_numeric . '/');
        $path = $root . $date_year . '/' . $date_month_numeric . '/';
        $json_file = $date_year . '-' . $date_month_numeric . '-' . $day_digits . '.json';

        if (!file_exists($path . $json_file)) {
            // Create a new json file in current date directory
            // and write data
            fopen($path . $json_file, 'w');
            file_put_contents($path . $json_file, json_encode($dailyData[$date_year][$date_month_numeric][$day_digits], JSON_PRETTY_PRINT));
        } else {
            # Existing Data
            $existing_json_file = file_get_contents($path . $json_file);
            $existing_array = json_decode($existing_json_file, true);

            foreach ($dailyData as $letter => $set) {
                if (!isset($existing_array[$letter])) {
                    $existing_array[$letter] = $set;
                } else {
                    $existing_array[$letter]['user'] = array_merge_recursive(
                        $existing_array[$letter]['user'],
                        $set['user']
                    );
                }
            }
            // update file
            file_put_contents($path . $json_file, json_encode($dailyData, JSON_PRETTY_PRINT));
        }
    }
}
archiveJSON($logfile_accepted_array, $root, $dailyData);

yes! if the directories (year/month) do not exist, they will be created if (!file_exists($path . $json_file)):

2022/12, 2023/1,2,3,4 and the json files with the right names (Y-m-d.json) in the right directory too.

expected json file content in 2023/02/2023-02-19.json:

{
    "BBB": {
        "user": {
            "a0:c9:a0:b6:79:3c": [
                "17:34:33"
            ]
        }
    }
}

expected json file content in 2023/02/2023-02-23.json:

{
    "AAAA": {
        "user": {
            "f0:8a:76:16:57:e8": ["12:21:09", "18:15:10"]
        }
    }
}

for the 1st i'm stuck here:

but if one of the letters has 2 entries on the same date as in this example: AAAA 2023 02 23 12:21:09 ... and AAAA 2023 02 23 18:15:10 ... then the 2023-02-23.json file all year entries written - unexpected json file content in 2023/02/2023-02-23.json:

{
    "2022": {
        "12": {
            "23": {
                "AAAA": {
                    "user": {
                        "dc:16:b2:4c:d2:e6": [
                            "21:37:56"
                        ]
                    }
                }
            }
        }
    },
    "2023": {
        "01": {
            "12": {
                "BBB": {
                    "user": {
                        "f0:8a:76:16:57:e8": [
                            "02:08:23"
                        ]
                    }
                }
            }
        },
        "02": {
            "19": {
                "BBB": {
                    "user": {
                        "a0:c9:a0:b6:79:3c": [
                            "17:34:33"
                        ]
                    }
                }
            },
            "23": {
                "AAAA": {
                    "user": {
                        "f0:8a:76:16:57:e8": [
                            "12:21:09",
                            "18:15:10"
                        ]
                    }
                }
            }
        },
        "03": {
            "19": {
                "CCCCC": {
                    "user": {
                        "f0:8a:76:16:57:e8": [
                            "17:07:26"
                        ]
                    }
                }
            }
        },
        "04": {
            "01": {
                "QQQ": {
                    "user": {
                        "a0:c9:a0:b6:79:3c": [
                            "00:00:03"
                        ]
                    }
                }
            }
        }
    }
}

else: if there are json data in the right directory with the right files, then complete them with the new entries:

secondly, I'm stuck here as well:

as above, all entries are written in each of the json files.

I would have to put $dailyData[$date_year][$date_month_numeric][$day_digits] in the right place. Or am I misunderstanding something?

i try many hours around. I spin around in circles.

Please don't be too harsh with me, because I'm an ambitious beginner and my head is getting tired.


Solution

  • You've presented a lot of code -- which I am finding difficult to read on my phone, but I believe your process is:

    1. Parse an array of lines and populate a multi-level hierarchical array
    2. Iterate the unique first 3 levels of the data structure, then
    3. Ensure that directories exist to accommodate the top three levels, then
    4. Access, decode, and recursively merge preexisting data in a given file (if it exists), then
    5. Save the new file contents.

    Untested Suggested Code:

    $fileLines = [
        "AAAA 2022 12 23 21:37:56 dc:16:b2:4c:d2:e6",
        "BBB 2023 01 12 02:08:23 f0:8a:76:16:57:e8",
        "BBB 2023 02 19 17:34:33 a0:c9:a0:b6:79:3c",
        "AAAA 2023 02 23 12:21:09 f0:8a:76:16:57:e8",
        "AAAA 2023 02 23 18:15:10 f0:8a:76:16:57:e8",
        "CCCCC 2023 03 19 17:07:26 f0:8a:76:16:57:e8",
        "QQQ 2023 04 01 00:00:03 a0:c9:a0:b6:79:3c"
    ];
    
    $result = [];
    foreach ($fileLines as $line) {
        [$group, $yyyy, $mm, $dd, $His, $id] = explode(' ', $line);
        $result[$yyyy][$mm][$dd][$group]['user'][$id][] = $His;
    }
    
    foreach ($result as $y => $months) {
        foreach ($months as $m => $days) {
            foreach ($days as $d => $groups) {
                $path = "$root/$y/$m";
                $filepath = "$path/$y-$m-$d.json";
                if (!file_exists($path)) {
                    mkdir($path, 0777, true);
                    $newContent = $groups;
                } elseif (!file_exists($filepath)) {
                    $newContent = $groups;
                } else {
                    $newContent = array_merge_recursive(
                        json_decode(file_get_contents($filepath), true),
                        $groups
                    );
                }
                file_put_contents(
                    $filepath,
                    json_encode($newContent, JSON_PRETTY_PRINT)
                );
            }
        }
    }