From 681888b47615e62c2f219a8538a0252feb89f400 Mon Sep 17 00:00:00 2001 From: alec_dev Date: Mon, 8 Sep 2025 22:38:10 -0500 Subject: [PATCH 1/6] Update nginx service volumes in docker-compose Comment out specific volume mounts for SSL certificates and add new volume mounts for Let's Encrypt and access logs. --- docker-compose.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3f456de..33a5a46 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,8 @@ version: '3.9' services: nginx: build: https://github.com/specify/nginx-with-github-auth.git#main + # build: + # context: ~/nginx-with-github-auth ports: - '80:80' - '443:443' @@ -10,8 +12,10 @@ services: - './sp7-stats/config/auth.conf:/etc/nginx/auth.conf:ro' - './sp7-stats/config/nginx.conf:/etc/nginx/conf.d/default.conf:ro' - './sp7-stats/:/var/www/:ro' - - './sp7-stats/config/fullchain.pem:/etc/letsencrypt/live/sp7-stats/fullchain.pem:ro' - - './sp7-stats/config/privkey.pem:/etc/letsencrypt/live/sp7-stats/privkey.pem:ro' + # - './sp7-stats/config/fullchain.pem:/etc/letsencrypt/live/sp7-stats/fullchain.pem:ro' + # - './sp7-stats/config/privkey.pem:/etc/letsencrypt/live/sp7-stats/privkey.pem:ro' + - '/etc/letsencrypt:/etc/letsencrypt:ro' + - './access-logs/:/var/log/nginx/external/:rw' networks: - nginx depends_on: From ebffd4e8528e82b2a7e777825cd1c17c35cea689 Mon Sep 17 00:00:00 2001 From: alec_dev Date: Mon, 8 Sep 2025 22:39:54 -0500 Subject: [PATCH 2/6] Refactor isa_number assignment with null coalescing --- sp7-stats/components/institutions.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sp7-stats/components/institutions.php b/sp7-stats/components/institutions.php index c7ca017..6246eda 100644 --- a/sp7-stats/components/institutions.php +++ b/sp7-stats/components/institutions.php @@ -74,7 +74,8 @@ function compile_institutions($lines_data, $file_name){ $institution = $line_data['institution']; $discipline = $line_data['discipline']; $collection = $line_data['collection']; - $isa_number = $line_data['isaNumber']; + // $isa_number = $line_data['isaNumber']; + $isa_number = $line_data['isaNumber'] ?? ''; $browser = $line_data['browser']; $domain = $line_data['domain']; $os = $line_data['os']; @@ -293,4 +294,4 @@ function sort_months($x,$y){ file_put_contents(WORKING_LOCATION.'institutions_id.json',json_encode($institutions4)); file_put_contents(WORKING_LOCATION.'institutions.json',json_encode($institutions3)); -} \ No newline at end of file +} From 132c89c159aefe76831a82c21c9d9f4710035b5a Mon Sep 17 00:00:00 2001 From: alec_dev Date: Mon, 8 Sep 2025 22:41:36 -0500 Subject: [PATCH 3/6] Modify Nginx config for HTTPS and access logging --- sp7-stats/config/nginx.conf | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/sp7-stats/config/nginx.conf b/sp7-stats/config/nginx.conf index 6ac09fa..1f3ce39 100644 --- a/sp7-stats/config/nginx.conf +++ b/sp7-stats/config/nginx.conf @@ -1,18 +1,44 @@ +# Outbound DNS for Lua http requests +# resolver 1.1.1.1 8.8.8.8 valid=300s; +# resolver_timeout 5s; + +# Trust store path on Alpine (nginx:alpine puts the bundle here) +# lua_ssl_trusted_certificate /etc/ssl/cert.pem; +# lua_ssl_verify_depth 5; + # See https://github.com/specify/nginx-with-github-auth include nginx-with-github-auth/http.conf; -# Redirect HTTP to HTTPs +# --- HTTP (port 80) --- server { listen 80 default_server; - server_name _; - return 301 https://$host$request_uri; + listen [::]:80 default_server; + + server_name stats.specifycloud.org; + + # Serve ACME challenge over HTTP without redirect + location ^~ /.well-known/acme-challenge/ { + root /var/www/stats; + try_files $uri =404; + } + + # Everything else: redirect to HTTPS + location / { + return 301 https://$host$request_uri; + } } +# --- HTTPS (port 443) --- server { listen 443 ssl default_server; + listen [::]:443 ssl default_server; + + server_name stats.specifycloud.org; + + # Use the certbot-standard live path for THIS domain name + ssl_certificate /etc/letsencrypt/live/stats.specifycloud.org-0001/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/stats.specifycloud.org-0001/privkey.pem; - ssl_certificate /etc/letsencrypt/live/sp7-stats/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/sp7-stats/privkey.pem; ssl_session_cache shared:SSL:10m; ssl_session_timeout 5m; ssl_prefer_server_ciphers on; @@ -21,19 +47,25 @@ server { include nginx-with-github-auth/server.conf; index index.php index.html; - server_name sp7-stats; keepalive_timeout 70; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/; + # -- added + access_log /var/log/nginx/external/access.log combined; + location = /capture { + # access_log /var/log/nginx/capture.log; # optional separate log + access_log /var/log/nginx/external/access.log combined; + add_header Content-Type text/plain; + return 204; + } + location ~ ^/.+\.php$ { include nginx-with-github-auth/location.conf; - include fastcgi_params; fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; } - } From e0dfda1fe32932312b30141c2685dd8c20d32cf3 Mon Sep 17 00:00:00 2001 From: alec_dev Date: Mon, 8 Sep 2025 22:42:52 -0500 Subject: [PATCH 4/6] Update require_once path in refresh_data.php --- sp7-stats/cron/refresh_data.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sp7-stats/cron/refresh_data.php b/sp7-stats/cron/refresh_data.php index 6dca7c8..732374e 100644 --- a/sp7-stats/cron/refresh_data.php +++ b/sp7-stats/cron/refresh_data.php @@ -5,4 +5,5 @@ global $no_gui; $no_gui = TRUE; -require_once('../refresh_data/index.php'); \ No newline at end of file +//require_once('../refresh_data/index.php'); +require_once __DIR__ . '/../refresh_data/index.php'; From 5f640b7b9e444462f55b9d130e797bfc15352108 Mon Sep 17 00:00:00 2001 From: alec_dev Date: Mon, 8 Sep 2025 22:44:25 -0500 Subject: [PATCH 5/6] Update require_once paths to use dirname function --- sp7-stats/refresh_data/index.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sp7-stats/refresh_data/index.php b/sp7-stats/refresh_data/index.php index 6f58cc8..bdb6710 100644 --- a/sp7-stats/refresh_data/index.php +++ b/sp7-stats/refresh_data/index.php @@ -1,6 +1,7 @@ Max RAM usage: '.round(memory_get_peak_usage()/1024/1024,2). - 'MB
RAM usage limit: '.ini_get('memory_limit')); \ No newline at end of file + 'MB
RAM usage limit: '.ini_get('memory_limit')); From 70bfc0a92454308db5babb8e82f3e01608bbbfb6 Mon Sep 17 00:00:00 2001 From: Grant Fitzsimmons <37256050+grantfitzsimmons@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:16:37 -0500 Subject: [PATCH 6/6] fix: merge remote changes --- docker-compose.yml | 16 +- sp7-stats/config/nginx.conf | 110 +++++---- sp7-stats/index.php | 469 +++++++++++++++++++----------------- 3 files changed, 326 insertions(+), 269 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 33a5a46..b37a2c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,8 +12,6 @@ services: - './sp7-stats/config/auth.conf:/etc/nginx/auth.conf:ro' - './sp7-stats/config/nginx.conf:/etc/nginx/conf.d/default.conf:ro' - './sp7-stats/:/var/www/:ro' - # - './sp7-stats/config/fullchain.pem:/etc/letsencrypt/live/sp7-stats/fullchain.pem:ro' - # - './sp7-stats/config/privkey.pem:/etc/letsencrypt/live/sp7-stats/privkey.pem:ro' - '/etc/letsencrypt:/etc/letsencrypt:ro' - './access-logs/:/var/log/nginx/external/:rw' networks: @@ -37,6 +35,20 @@ services: networks: - nginx + certbot: + image: certbot/certbot + container_name: certbot + volumes: + - '/etc/letsencrypt:/etc/letsencrypt' + - './sp7-stats/:/var/www/certbot/' + - '/var/run/docker.sock:/var/run/docker.sock' + entrypoint: > + sh -c "trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --deploy-hook 'docker exec sp7-stats-nginx-1 nginx -s reload'; sleep 12h; done" + networks: + - nginx + depends_on: + - nginx + networks: nginx: diff --git a/sp7-stats/config/nginx.conf b/sp7-stats/config/nginx.conf index 1f3ce39..d43820e 100644 --- a/sp7-stats/config/nginx.conf +++ b/sp7-stats/config/nginx.conf @@ -11,61 +11,71 @@ include nginx-with-github-auth/http.conf; # --- HTTP (port 80) --- server { - listen 80 default_server; - listen [::]:80 default_server; + listen 80 default_server; + listen [::]:80 default_server; - server_name stats.specifycloud.org; + server_name stats.specifycloud.org sp7-stats.specifycloud.org; - # Serve ACME challenge over HTTP without redirect - location ^~ /.well-known/acme-challenge/ { - root /var/www/stats; - try_files $uri =404; - } + # Serve ACME challenge over HTTP without redirect + location ^~ /.well-known/acme-challenge/ { + root /var/www/; + try_files $uri =404; + } - # Everything else: redirect to HTTPS - location / { - return 301 https://$host$request_uri; - } + # Everything else: redirect to HTTPS + location / { + return 301 https://$host$request_uri; + } } # --- HTTPS (port 443) --- server { - listen 443 ssl default_server; - listen [::]:443 ssl default_server; - - server_name stats.specifycloud.org; - - # Use the certbot-standard live path for THIS domain name - ssl_certificate /etc/letsencrypt/live/stats.specifycloud.org-0001/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/stats.specifycloud.org-0001/privkey.pem; - - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 5m; - ssl_prefer_server_ciphers on; - - include auth.conf; - include nginx-with-github-auth/server.conf; - - index index.php index.html; - keepalive_timeout 70; - error_log /var/log/nginx/error.log; - access_log /var/log/nginx/access.log; - root /var/www/; - - # -- added - access_log /var/log/nginx/external/access.log combined; - location = /capture { - # access_log /var/log/nginx/capture.log; # optional separate log - access_log /var/log/nginx/external/access.log combined; - add_header Content-Type text/plain; - return 204; - } - - location ~ ^/.+\.php$ { - include nginx-with-github-auth/location.conf; - include fastcgi_params; - fastcgi_pass php:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; - } + listen 443 ssl default_server; + listen [::]:443 ssl default_server; + + server_name stats.specifycloud.org sp7-stats.specifycloud.org; + + # Use the certbot-standard live path for THIS domain name + ssl_certificate /etc/letsencrypt/live/sp7-stats.specifycloud.org/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sp7-stats.specifycloud.org/privkey.pem; + + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 5m; + ssl_prefer_server_ciphers on; + + include auth.conf; + include nginx-with-github-auth/server.conf; + + index index.php index.html; + keepalive_timeout 70; + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; + root /var/www/; + + access_log /var/log/nginx/external/access.log combined; + + location = /capture { + # Allow browser JS to call this cross-origin + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always; + add_header 'Access-Control-Max-Age' 86400 always; + + # Handle preflight (some browsers/frameworks trigger this) + if ($request_method = OPTIONS) { + return 204; + } + + access_log /var/log/nginx/external/access.log combined; + add_header Content-Type text/plain; + return 204; + } + + location ~ ^/.+\.php$ { + include nginx-with-github-auth/location.conf; + include fastcgi_params; + fastcgi_pass php:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; + } } diff --git a/sp7-stats/index.php b/sp7-stats/index.php index 385139c..3a0f978 100644 --- a/sp7-stats/index.php +++ b/sp7-stats/index.php @@ -8,28 +8,28 @@ $files = array_reverse($files); if(array_key_exists('file_1',$_GET) && file_exists($target_dir.$_GET['file_1'].$target_extension) && strlen($_GET['file_1'])===5 && is_numeric($_GET['file_1'])) - $first_day = intval($_GET['file_1']); + $first_day = intval($_GET['file_1']); else - $first_day = FALSE; + $first_day = FALSE; if(array_key_exists('file_2',$_GET) && file_exists($target_dir.$_GET['file_2'].$target_extension) && strlen($_GET['file_2'])===5 && is_numeric($_GET['file_2'])) - $last_day = intval($_GET['file_2']); + $last_day = intval($_GET['file_2']); else - $last_day = FALSE; + $last_day = FALSE; if(array_key_exists('date',$_GET)){ - $_GET['date'] = urldecode($_GET['date']); + $_GET['date'] = urldecode($_GET['date']); - $date_info = date_parse_from_format(YEAR_FORMATTER.' '.MONTH_FORMATTER.' '.DAY_FORMATTER,$_GET['date']); + $date_info = date_parse_from_format(YEAR_FORMATTER.' '.MONTH_FORMATTER.' '.DAY_FORMATTER,$_GET['date']); - if(strlen($date_info['month'])==1) - $date_info['month'] = '0'.$date_info['month']; + if(strlen($date_info['month'])==1) + $date_info['month'] = '0'.$date_info['month']; - if(strlen($date_info['day'])==1) - $date_info['day'] = '0'.$date_info['day']; + if(strlen($date_info['day'])==1) + $date_info['day'] = '0'.$date_info['day']; - $unix_time = strtotime($date_info['month'].'/'.$date_info['day'].'/'.$date_info['year']); - $first_day = $last_day = intval($unix_time/86400); + $unix_time = strtotime($date_info['month'].'/'.$date_info['day'].'/'.$date_info['year']); + $first_day = $last_day = intval($unix_time/86400); } @@ -41,122 +41,122 @@ $times = 0; if(array_key_exists('hide',$_GET) && is_numeric($_GET['hide']) && $_GET['hide']>0) - $times = intval($_GET['hide']); + $times = intval($_GET['hide']); foreach($files as $file){ - $unix_time = explode('/', $file); - $unix_time = end($unix_time); - $unix_time = explode('.', $unix_time); - $unix_time = intval($unix_time[0]); + $unix_time = explode('/', $file); + $unix_time = end($unix_time); + $unix_time = explode('.', $unix_time); + $unix_time = intval($unix_time[0]); - $selected_1_append = ''; - $selected_2_append = ''; + $selected_1_append = ''; + $selected_2_append = ''; - if(!$first_unix_begin) - $first_unix_begin = $unix_time; + if(!$first_unix_begin) + $first_unix_begin = $unix_time; - if(!$first_day) - $first_day = $unix_time; + if(!$first_day) + $first_day = $unix_time; - if(!$last_day) - $last_day = $unix_time; + if(!$last_day) + $last_day = $unix_time; - if($first_day>$last_day) - [$first_day,$last_day] = [$last_day,$first_day]; + if($first_day>$last_day) + [$first_day,$last_day] = [$last_day,$first_day]; - if($unix_time == $first_day) - $selected_1_append = 'selected'; + if($unix_time == $first_day) + $selected_1_append = 'selected'; - if($unix_time == $last_day) - $selected_2_append = 'selected'; + if($unix_time == $last_day) + $selected_2_append = 'selected'; - if($unix_time >= $first_day && $unix_time <= $last_day){ + if($unix_time >= $first_day && $unix_time <= $last_day){ - $data = json_decode(file_get_contents($file),TRUE); - $institutions = array_merge_recursive($institutions,$data); + $data = json_decode(file_get_contents($file),TRUE); + $institutions = array_merge_recursive($institutions,$data); - } + } - $human_time = unix_days_to_human_time($unix_time); + $human_time = unix_days_to_human_time($unix_time); - $result_1 .= ''; - $result_2 .= ''; + $result_1 .= ''; + $result_2 .= ''; } foreach($institutions as $institution_name => &$disciplines){ - foreach($disciplines as $discipline_name => &$collections){ + foreach($disciplines as $discipline_name => &$collections){ - foreach($collections as $collection_name => &$collection){ + foreach($collections as $collection_name => &$collection){ - if(is_array($collection['count']))//fix array_merge_recursive creating an array out of 'count' - $collection['count'] = array_sum($collection['count']); + if(is_array($collection['count']))//fix array_merge_recursive creating an array out of 'count' + $collection['count'] = array_sum($collection['count']); - if($collection['count']<$times){ - unset($collections[$collection_name]); - continue; - } + if($collection['count']<$times){ + unset($collections[$collection_name]); + continue; + } - $cols = ['sp7_version','sp6_version','isa_number','ip_address','browser','os','domain']; - foreach($cols as $col) - $collection[$col] = array_unique($collection[$col]); + $cols = ['sp7_version','sp6_version','isa_number','ip_address','browser','os','domain']; + foreach($cols as $col) + $collection[$col] = array_unique($collection[$col]); - } + } - if(count($collections)==0) - unset($disciplines[$discipline_name]); + if(count($collections)==0) + unset($disciplines[$discipline_name]); - } + } - if(count($disciplines)==0) - unset($institutions[$institution_name]); + if(count($disciplines)==0) + unset($institutions[$institution_name]); } ?> Show results from till
- + +
if($view=='0' || $view=='00') { ?> - -
    + const search_mode = 'list'; + +
      $disciplines){ + foreach($institutions as $institution => $disciplines){ - echo '
    1. ' . urldecode($institution) . '
        '; + echo '
      • ' . urldecode($institution) . '
          '; - foreach($disciplines as $discipline => $collections){ + foreach($disciplines as $discipline => $collections){ - echo '
        • ' . urldecode($discipline) . '
            '; + echo '
          • ' . urldecode($discipline) . '
              '; - foreach($collections as $collection => $data){ + foreach($collections as $collection => $data){ - echo '
            • - '.urldecode($collection).' ['.$data['count'].'] -
              Specify 7 versions:
                '; + echo '
              • + '.urldecode($collection).' ['.$data['count'].'] +
                Specify 7 versions:
                  '; - foreach($data['sp7_version'] as $version) - echo '
                • ' . $version . '
                • '; + foreach($data['sp7_version'] as $version) + echo '
                • ' . $version . '
                • '; - echo '
                Specify 6 versions:
                  '; + echo '
                Specify 6 versions:
                  '; - foreach($data['sp6_version'] as $version) - echo '
                • ' . $version . '
                • '; + foreach($data['sp6_version'] as $version) + echo '
                • ' . $version . '
                • '; - echo '
                Domains:
                  '; + echo '
                Domains:'; + echo '
              '; - if(count($data['isa_number']) > 0) - echo 'ISA Numbers: ' . implode(', ', $data['isa_number']).'
              '; + if(count($data['isa_number']) > 0) + echo 'ISA Numbers: ' . implode(', ', $data['isa_number']).'
              '; - echo 'IP Addresses:
                '; + echo 'IP Addresses: - Browsers:
                  '; + echo '
                + Browsers:
                  '; - foreach($data['browser'] as $browser) - echo '
                • ' . $browser . '
                • '; + foreach($data['browser'] as $browser) + echo '
                • ' . $browser . '
                • '; - echo '
                - Operating Systems:
                  '; + echo '
                + Operating Systems:
                  '; - foreach($data['os'] as $os) - echo '
                • ' . $os . '
                • '; + foreach($data['os'] as $os) + echo '
                • ' . $os . '
                • '; - echo '

                '; + echo '

            • '; - $collection_count++; - $report_count+=$data['count']; + if (isset($data['collectionObjectCount'])) { + echo 'Collection Objects: ' . intval($data['collectionObjectCount']) . '
              '; + } + if (isset($data['collectionCount'])) { + echo 'Collections: ' . intval($data['collectionCount']) . '
              '; + } + if (isset($data['userCount'])) { + echo 'Users: ' . intval($data['userCount']) . '
              '; + } - } + $collection_count++; + $report_count+=$data['count']; - echo '
          • '; + } - $discipline_count++; + echo '
        • '; - } + $discipline_count++; - echo '
      • '; + } - } + echo '
    2. '; - echo '
    '; + } + + echo '
'; } elseif($view=='1' || $view=='11'){ ?> - + - - - - - - - - - - + + + + + + + + + ',$cell_count-$last_cell).''; + $last_cell=0; + } - if($position<=$last_cell){ - echo str_repeat('',$cell_count-$last_cell).''; - $last_cell=0; - } + if($value=='') + return; - if($value=='') - return; + if($last_cell==0) + echo ''; - if($last_cell==0) - echo ''; + if($class!='') + $class = ' class="'.$class.'"'; - if($class!='') - $class = ' class="'.$class.'"'; + echo str_repeat('',$position-$last_cell-1).''.$value.''; - echo str_repeat('',$position-$last_cell-1).''.$value.''; + $last_cell = $position; - $last_cell = $position; + } - } + $institution_count = count($institutions); + $discipline_count = 0; + $collection_count = 0; + $report_count = 0; + foreach($institutions as $institution => $disciplines){ - $institution_count = count($institutions); - $discipline_count = 0; - $collection_count = 0; - $report_count = 0; - foreach($institutions as $institution => $disciplines){ + echo ''; - echo ''; + to_cell(1,urldecode($institution),'institution'); - to_cell(1,urldecode($institution),'institution'); + foreach($disciplines as $discipline => $collections){ - foreach($disciplines as $discipline => $collections){ + to_cell(2,urldecode($discipline),'discipline'); - to_cell(2,urldecode($discipline),'discipline'); + foreach($collections as $collection => $data){ + to_cell(3,''.urldecode($collection).' ['.$data['count'].']'); + to_cell(4,'Specify 7 versions'); + foreach($data['sp7_version'] as $version) + to_cell(5,$version); + to_cell(4,'Specify 6 versions'); + foreach($data['sp6_version'] as $version) + to_cell(5,$version); + to_cell(4,'Domains'); + foreach($data['domain'] as $domain) + to_cell(5,'' . $domain . ''); - foreach($collections as $collection => $data){ - to_cell(3,''.urldecode($collection).' ['.$data['count'].']'); - to_cell(4,'Specify 7 versions'); - foreach($data['sp7_version'] as $version) - to_cell(5,$version); - to_cell(4,'Specify 6 versions'); - foreach($data['sp6_version'] as $version) - to_cell(5,$version); - to_cell(4,'Domains'); - foreach($data['domain'] as $domain) - to_cell(5,'' . $domain . ''); + if(count($data['isa_number'])>0){ + to_cell(4,'ISA Numbers'); + to_cell(5,implode(', ',$data['isa_number'])); + } - if(count($data['isa_number'])>0){ - to_cell(4,'ISA Numbers'); - to_cell(5,implode(', ',$data['isa_number'])); - } + to_cell(4,'IP Addresses'); + foreach($data['ip_address'] as $ip_address) + to_cell(5,''.$ip_address.''); - to_cell(4,'IP Addresses'); - foreach($data['ip_address'] as $ip_address) - to_cell(5,''.$ip_address.''); + to_cell(4,'Browsers'); + foreach($data['browser'] as $browser) + to_cell(5,$browser); - to_cell(4,'Browsers'); - foreach($data['browser'] as $browser) - to_cell(5,$browser); + to_cell(4,'Operating Systems'); - to_cell(4,'Operating Systems'); + foreach($data['os'] as $os) + to_cell(5,$os); - foreach($data['os'] as $os) - to_cell(5,$os); + if (isset($data['collectionObjectCount'])) { + to_cell(4, 'Collection Objects'); + to_cell(5, intval($data['collectionObjectCount'])); + } + else { + to_cell(4, 'Collection Objects'); + to_cell(5, 'N/A'); + } + if (isset($data['collectionCount'])) { + to_cell(4, 'Collections'); + to_cell(5, intval($data['collectionCount'])); + } + else { + to_cell(4, 'Collections'); + to_cell(5, 'N/A'); + } + if (isset($data['userCount'])) { + to_cell(4, 'Users'); + to_cell(5, intval($data['userCount'])); + } + else { + to_cell(4, 'Users'); + to_cell(5, 'N/A'); + } - $collection_count++; - $report_count+=$data['count']; + $collection_count++; + $report_count+=$data['count']; - } + } - $discipline_count++; + $discipline_count++; - } + } - echo ''; + echo ''; - } + } - to_cell(0); + to_cell(0); - echo '
InstitutionDisciplineCollectionPropertyValue
InstitutionDisciplineCollectionPropertyValue
'; + echo ''; } ?>