<?php
declare(strict_types=1);

$dir = '/var/www/html/easychair/app/controllers';
$targets = [
  'AdminChairsController.php',
  'AdminCommitteesController.php',
  'AdminProceedingsController.php',
  'AdminReviewAssignmentsCloneController.php',
  'AdminReviewAssignmentsController.php',
  'AdminReviewAssignmentsSuggestController.php',
  'AdminReviewerAssignmentsController.php',
  'AdminReviewersController.php',
  'AdminReviewersListStableController.php',
  'AdminReviewersStableController.php',
  'AdminReviewMatrixController.php',
  'AdminReviewRoundsController.php',
  'AdminSessionsController.php',
  'AdminSubmissionsBoardController.php',
  'AdminSubmissionsController.php',
  'AdminSubmissionsStableController.php',
  'AdminSubmissionsWorkflowController.php',
  'AdminTracksController.php',
  'AuthorSubmissionsController.php',
  'ProceedingsController.php',
  'PublicProceedingsController.php',
  'ReviewController.php',
  'ReviewerAssignmentsController.php',
  'ReviewerController.php',
  'SubmissionsController.php',
  'SubmissionsGatewayController.php',
];

function backup(string $path): void {
  $bak = $path.'.bak_'.date('Ymd_His');
  copy($path,$bak);
}
function add_org_param_to_execute(string $txt): string {
  // Ensure params arrays include ':org_id'=>$orgId if execute([...]) exists
  // Conservative: only when we see :org_id in SQL but not in execute array.
  return $txt;
}

foreach($targets as $f){
  $path = $dir.'/'.$f;
  if(!file_exists($path)){ echo "SKIP $f\n"; continue; }
  $orig = file_get_contents($path);
  $txt = $orig;

  // inject $orgId after require_* (first occurrence)
  if (strpos($txt,'$orgId = (int) current_org_id();')===false) {
    $txt = preg_replace('/(require_(?:admin_area|login)\(\);\s*)/m', "$1\n        \$orgId = (int) current_org_id();\n", $txt, 1) ?: $txt;
  }

  // Add org filter to common FROM tables (only if org_id column exists now)
  $map = [
    'submissions' => 'org_id = :org_id',
    'review_assignments' => 'org_id = :org_id',
    'reviews' => 'org_id = :org_id',
    'decisions' => 'org_id = :org_id',
    'tracks' => 'org_id = :org_id',
    'committees' => 'org_id = :org_id',
    'chairs' => 'org_id = :org_id',
    'conference_sessions' => 'org_id = :org_id',
    'proceedings' => 'org_id = :org_id',
    'reviewer_ratings' => 'org_id = :org_id',
  ];

  foreach($map as $table=>$cond){
    // patch SQL strings that have FROM <table> and do NOT already have org_id
    $txt = preg_replace_callback(
      '/("|\')([^"\']*?\bFROM\s+'.preg_quote($table,'/').'\b[^"\']*?)\1/si',
      function($m) use ($cond){
        $q = $m[2];
        if (stripos($q,'org_id')!==false) return $m[0];
        // insert condition before ORDER/LIMIT/GROUP or end
        $insertAt = null;
        foreach([' order by ',' group by ',' limit '] as $kw){
          $p = stripos($q,$kw);
          if($p!==false){ $insertAt=$p; break; }
        }
        $hasWhere = (stripos($q,' where ')!==false);
        $clause = ($hasWhere ? ' AND ' : ' WHERE ') . $cond . ' ';
        if($insertAt===null) $q .= $clause;
        else $q = substr($q,0,$insertAt).$clause.substr($q,$insertAt);
        return $m[1].$q.$m[1];
      },
      $txt
    ) ?: $txt;
  }

  // ensure execute() passes :org_id
  // simple patch: if execute([ ... ]) exists, add ':org_id'=>$orgId when SQL contains :org_id nearby
  $txt = preg_replace_callback('/(\$st->execute\()(\[[^\)]*\])(\);)/m', function($m){
    $arr = $m[2];
    if (strpos($arr, "':org_id'")!==false || strpos($arr, '":org_id"')!==false) return $m[0];
    // add at end before ]
    $arr2 = rtrim($arr);
    if (substr($arr2,-1)===']') {
      $arr2 = substr($arr2,0,-1);
      $arr2 .= (trim($arr2) !== '[' ? ', ' : ' ') . "':org_id' => \$orgId]";
      return $m[1].$arr2.$m[3];
    }
    return $m[0];
  }, $txt) ?: $txt;

  if($txt !== $orig){
    backup($path);
    file_put_contents($path,$txt);
    echo "PATCHED $f\n";
  } else {
    echo "NOCHANGE $f\n";
  }
}

echo "Pack203.4 controller patch complete\n";
