public static function getTenantProperty($applicationID, $tenantID, $userID, $property)
 {
     Log::debug('retrieving tenant property ' . $property . " for tenant ID=" . $tenantID, 1);
     $key = $applicationID . ":" . $tenantID . ":" . $property;
     $value = Cache::getValue($key);
     if (!$value) {
         // cache miss. Need to retrieve from database
         $class = new Tenant($userID, $tenantID);
         $query = '';
         if ($class->hasField($property)) {
             // this is one the fields on the tenant table
             $query = 'select ' . $property . ' from tenant where id=' . Database::queryNumber($tenantID);
         } else {
             // this might be a dynamically-set property
             $query = 'select value from tenantSetting where setting= ' . Database::queryString($property) . ' and tenantid=' . Database::queryNumber($tenantID);
         }
         $data = Database::executeQuery($query);
         if ($data) {
             if ($row = $data->fetch_row()) {
                 $value = $row[0];
             } else {
                 Log::debug('Warning: tenant property requested but not found: ' . $property . ' (tenantid= ' . $tenantID . ')', 5);
                 $value = '*undefined*';
             }
             Cache::putValue($key, $value);
         }
     }
     if ($value == '*undefined*') {
         // little dance we do here, so we can still cache the null
         $value = null;
     }
     return $value;
 }