diff --git a/cron/cleanup.php b/cron/cleanup.php index 46fc1e6..69a9a5c 100644 --- a/cron/cleanup.php +++ b/cron/cleanup.php @@ -28,7 +28,10 @@ reportErrorLogEntries(); /* remove screenshots that are missing their screenshot and thumbnail files */ removeScreenshotsWithMissingFiles(); - +/* check and notify maintainers about data they have pending in their queues */ +/* if they don't process the data soon enough we'll strip them of their maintainer */ +/* status since they aren't really maintaining the application/version */ +maintainerCheck(); /* @@ -333,4 +336,13 @@ function removeScreenshotsWithMissingFiles() // log out as user $oUser->logout(); } + +/* check and notify maintainers about data they have pending in their queues */ +/* if they don't process the data soon enough we'll strip them of their maintainer */ +/* status since they aren't really maintaining the application/version */ +function maintainerCheck() +{ + maintainer::notifyMaintainersOfQueuedData(); +} + ?> diff --git a/include/maintainer.php b/include/maintainer.php index 84af1e9..d4d0db4 100644 --- a/include/maintainer.php +++ b/include/maintainer.php @@ -6,6 +6,136 @@ require_once(BASE."include/application.php"); require_once(BASE."include/version.php"); require_once(BASE."include/user.php"); +//FIXME: when we have php5 move this into the maintainer class as a constant var +define('iNotificationIntervalDays', 7); // days between each notification level + +// class that can retrieve the queued entries for a given maintainer instance +class queuedEntries +{ + var $aVersionIds; + var $aScreenshotIds; + var $aTestDataIds; + + var $oMaintainer; // the maintainer we are retrieving entries for + + function queuedEntries($oMaintainer) + { + $this->oMaintainer = $oMaintainer; + + $this->aVersionIds = array(); + $this->aScreenshotIds = array(); + $this->aTestDataIds = array(); + } + + // returns true if none of the arrays have any entries in them + function isEmpty() + { + if((count($this->aVersionIds) == 0) && + (count($this->aScreenshotIds) == 0) && + (count($this->aTestDataIds) == 0)) + { + return true; + } + + return false; + } + + function retrieveQueuedEntries() + { + $bDebugOutputEnabled = false; + + if($bDebugOutputEnabled) + echo "retrieveQueuedEntries() starting\n"; + + //////////////////////////////////// + // retrieve a list of versions to check for queued data + $aVersionsToCheck = array(); + if($this->oMaintainer->bSuperMaintainer) + { + if($bDebugOutputEnabled) + echo "maintainer is super maintainer\n"; + + $oApp = new Application($this->oMaintainer->iAppId); + + //TODO: would like to rely on the constructor but we might be a user with 'admin' + // privileges and that would mean we would end up retrieved queued versions for + // this application or unqueued versions depending on which user we were + $hResult = $oApp->_internal_retrieve_all_versions(); + + while($oVersionRow = mysql_fetch_object($hResult)) + { + if($bDebugOutputEnabled) + { + echo "oVersionRow is: "; + print_r($oVersionRow); + } + + $oVersion = new Version($oVersionRow->versionId); + + if($bDebugOutputEnabled) + { + echo "Processing version: "; + print_r($oVersion); + } + + if($oVersion->sQueued == "true") + { + $this->aVersions[] = $oVersion->objectGetId(); + } else // version isn't queued + { + // add the unqueued version to the list of versions to check for queued data + $aVersionsToCheck[] = $oVersion->iVersionId; + } + } + } else // just a normal maintainer + { + $aVersionsToCheck[] = $this->oMaintainer->iVersionId; + if($bDebugOutputEnabled) + echo "Normal maintainer of version ".$this->oMaintainer->iVersionId."\n"; + } + + // go through all of the verions to see what queued data they have + foreach($aVersionsToCheck as $iVersionId) + { + if($bDebugOutputEnabled) + echo "Processing iVersionId of ".$iVersionId."\n"; + + ////////////////// + // queued testdata + + // retrieve queued testdata for this version + $sQuery = "select * from testResults where versionId = '?' and queued = '?'"; + $hResult = query_parameters($sQuery, $iVersionId, "true"); + + // go through the test results looking for the oldest queued data + while($oTestingRow = mysql_fetch_object($hResult)) + { + if($bDebugOutputEnabled) + echo "\tQueued TestData found\n"; + $oTestData = new TestData(null, $oTestingRow); + + $this->aTestDataIds[] = $oTestData->objectGetId(); + } + // queued testdata + ////////////////// + + + //////////////////// + // queued screenshots + $sQuery = "select * from appData where type = 'screenshot' and versionId = '?' and queued = '?'"; + $hResult = query_parameters($sQuery, $iVersionId, "true"); + while($oScreenshotRow = mysql_fetch_object($hResult)) + { + $oScreenshot = new Screenshot(null, $oScreenshotRow); + + $this->aScreenshotIds[] = $oScreenshot->objectGetId(); + } + // queued screenshots + ////////////////////// + } + } +} + class maintainer { var $iMaintainerId; @@ -14,12 +144,21 @@ class maintainer var $iUserId; var $sMaintainReason; var $bSuperMaintainer; - var $aSubmitTime; + var $aSubmitTime; //FIXME: should be 'sSubmitTime' var $bQueued; var $sReplyText; + // parameters used in the queued data notification system + // that lets maintainers know that their applications/versions have + // queued data for them to process + var $iNotificationLevel; // the current warning level of this maintainer + var $sNotificationTime; // the time when we last warned this maintainer + function maintainer($iMaintainerId = null, $oRow = null) { + // set a default notification level of 0 + $this->iNotificationLevel = 0; + if(!$iMaintainerId && !$oRow) return; @@ -41,6 +180,9 @@ class maintainer $this->bSuperMaintainer = $oRow->superMaintainer; $this->aSubmitTime = $oRow->submitTime; $this->bQueued = $oRow->queued; + + $this->iNotificationLevel = $oRow->notificationLevel; + $this->sNotificationTime = $oRow->notificationTime; } } @@ -264,6 +406,7 @@ class maintainer return new maintainer($oRow->maintainerId); } + // returns the number of applications/versions a particular user maintains function getMaintainerCountForUser($oUser, $bSuperMaintainer) { $sQuery = "SELECT count(*) as cnt from appMaintainers WHERE userid = '?' AND superMaintainer = '?'". @@ -672,6 +815,301 @@ class maintainer { return FALSE; } + + // level 0 is from 0 to iNotificationIntervalDays + // level 1 is from (iNotificationIntervalDays + 1) to (iNotificationIntervalDays * 2) + // level 2 is from (iNotificationIntervalDays * 2 + 1) to (iNotificationIntervalDays * 3) + // level 3 is beyond (iNotificationIntervalDays * 3) + function notifyMaintainerOfQueuedData() + { + $bDebugOutputEnabled = false; + + if($bDebugOutputEnabled) + echo "notifyMaintainerOfQueuedData()\n"; + + // if a maintainer has an non-zero warning level + // has it been enough days since we last warned them to warrent + // checking to see if we should warn them again? + if($this->iNotificationLevel != 0) + { + $iLastWarnTime = strtotime($this->sNotificationTime); + $iLastWarnAgeInSeconds = strtotime("now") - $iLastWarnTime; + + if($bDebugOutputEnabled) + echo "iLastWarnAgeInSeconds: ".$iLastWarnAgeInSeconds."\n"; + + // if it hasn't been at least $iNotificationIntervalDays since the last + // warning we can skip even checking the user + if($iLastWarnAgeInSeconds < (iNotificationIntervalDays * 24 * 60 * 60)) + { + if($bDebugOutputEnabled) + echo "iNotificationIntervalDays has not elapsed, skipping checking the user\n"; + return null; + } + } + + if($bDebugOutputEnabled) + echo "notification level is: ".$this->iNotificationLevel."\n"; + + // instantiate the user so we can retrieve particular values + $oUser = new User($this->iUserId); + + if($bDebugOutputEnabled) + { + echo "this->iUserId: ".$this->iUserId."\n"; + print_r($oUser); + } + + // get the time the user signed up + // if queued entries have been queued since before the user signed up + // we can't punish them for this fact + $iMaintainerSignupTime = strtotime($this->aSubmitTime); + + if($bDebugOutputEnabled) + echo "iMaintainerSignupTime: ".$iMaintainerSignupTime."\n"; + + // store the oldest queued entry + $iOldestQueuedEntryTime = strtotime("now"); + + // construct the subject of the notification email that we may send + $sSubject = "Notification of queued data for "; + $sMsg = "You are receiving this email to notify you that there is queued data"; + $sMsg.=" for the "; + if($this->bSuperMaintainer) + { + $oApp = new Application($this->iAppId); + $sSubject.= $oApp->sName; + $sMsg.='application, '.$oApp->objectMakeLink().', that you maintain.'."\n"; + } else + { + $sFullname = version::fullName($this->iVersionId); + $oVersion = new Version($this->iVersionId); + $sSubject.= $sFullname; + $sMsg.='version, '.$sFullname. + ', that you maintain.'."\n"; + } + $sSubject.=" ready for your processing"; + + // retrieve the queued entries + $oQueuedEntries = new queuedEntries($this); + $oQueuedEntries->retrieveQueuedEntries(); + if($oQueuedEntries->isEmpty()) + { + if($bDebugOutputEnabled) + echo "No entries, returning\n"; + + //no entries, we might as well return here + return; + } + + // process each of the queued versions + foreach($oQueuedEntries->aVersionIds as $iVersionId) + { + $oVersion = new Version($iVersionId); + + $sMsg .= 'Version '.$sFullname. + ' is queued and ready for processing.'; + + $iSubmitTime = strtotime($oVersion->sSubmitTime); + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + if(count($oQueuedEntries->aVersionIds) != 0) + { + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg = 'Please visit AppDB Version queue to process queued versions for applications you maintain.\n'; + } + + ////////////////// + // queued testdata + + // go through the test results looking for the oldest queued data + foreach($oQueuedEntries->aTestDataIds as $iTestDataId) + { + if($bDebugOutputEnabled) + echo "Testresult found\n"; + $oTestData = new TestData($iTestDataId); + + $iSubmitTime = strtotime($oTestData->sSubmitTime); + if($bDebugOutputEnabled) + echo "iSubmitTime is ".$iSubmitTime."\n"; + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + if($bDebugOutputEnabled) + echo "setting new oldest time\n"; + + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + $iTestResultCount = count($oQueuedEntries->aTestDataIds); + if($iTestResultCount != 0) + { + // grammar is slightly different for singular vs. plural + if($iTestResultCount == 1) + $sMsg.="There is $iTestResultCount queued test result. "; + else + $sMsg.="There are $iTestResultCount queued test results. "; + + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg .= 'Please visit AppDB Test Data queue to process queued test data for versions you maintain.\r\n'; + } + // queued testdata + ////////////////// + + + //////////////////// + // queued screenshots + foreach($oQueuedEntries->aScreenshotIds as $iScreenshotId) + { + $oScreenshot = new Screenshot($iScreenshotId); + + $iSubmitTime = strtotime($oScreenshot->sSubmitTime); + + // is this submission time older than the oldest queued time? + // if so this is the new oldest time + if($iSubmitTime < $iOldestQueuedEntryTime) + { + $iOldestQueuedEntryTime = $iSubmitTime; + } + } + + // if the oldest queue entry time is older than the time the maintainer + // signed up, use the maintainer signup time as the oldest time + if($iOldestQueuedEntryTime < $iMaintainerSignupTime) + $iOldestQueuedEntryTime = $iMaintainerSignupTime; + + + // if we found any queued screenshots add the screenshot queue processing link + // to the email + if(count($oQueuedEntries->aScreenshotIds) != 0) + { + // FIXME: should use a function to generate these urls and use it here and + // in sidebar_maintainer.php and sidebar_admin.php + $sMsg .= 'Please visit Screenshot queue to process queued screenshots for versions you maintain.\r\n'; + } + + // queued screenshots + ////////////////////// + + // compute the age in seconds of the oldest entry + $iAgeInSeconds = strtotime("now") - $iOldestQueuedEntryTime; + + // compute the target warning level based on the age and the notification interval + // we divide the age by the number of seconds in a day multiplied by the days per notification interval + $iTargetLevel = (integer)($iAgeInSeconds / (iNotificationIntervalDays * 24 * 60 * 60)); + + if($bDebugOutputEnabled) + { + echo "iOldestQueuedEntryTime is $iOldestQueuedEntryTime\n"; + echo "iAgeInSeconds is $iAgeInSeconds\n"; + echo "iNotificationIntervalDays is ".iNotificationIntervalDays."\n"; + echo "strtotime(now) is ".strtotime("now")."\n"; + echo "iTargetLevel is ".$iTargetLevel."\n"; + } + + // if the target level is less than the current level, adjust the current level + // This takes into account the entries in the users queue that may have been processed + if($iTargetLevel < $this->iNotificationLevel) + { + if($bDebugOutputEnabled) + echo "Using iTargetLevel of $iTargetLevel\n"; + $this->iNotificationLevel = $iTargetLevel; + } + + // if the target level is higher than the current level then adjust the + // current level up by 1 + // NOTE: we adjust up by one because we want to ensure that we go through + // notification levels one at a time + if($iTargetLevel > $this->iNotificationLevel) + { + if($bDebugOutputEnabled) + echo "Increasing notification level of $this->iNotificationLevel by 1\n"; + $this->iNotificationLevel++; + } + + switch($this->iNotificationLevel) + { + case 0: // lowest level, no notification + // nothing to do here + break; + case 1: // send the first notification + // nothing to do here, the first notification is just a reminder + $sMsg.= "\n\nThanks,\n"; + $sMsg.= "Appdb Admins"; + break; + case 2: // send the second notification, notify them that if the queued entries aren't + // processed after another $iNotificationIntervalDays that + // we'll have to remove their maintainership for this application/version + // so a more active person can fill the spot + $sMsg.= "\nThis your second notification of queued entries. If the queued entries are"; + $sMsg.= " not processed within the next ".iNotificationIntervalDays. "we will remove"; + $sMsg.= " your maintainership for this application/version so a more active person"; + $sMsg.= " can fill the spot."; + $sMsg.= "\n\nThanks,\n"; + $sMsg.= "Appdb Admins"; + break; + case 3: // remove their maintainership + $this->delete(); // delete ourselves from the database + break; + } + + // save the notification level and notification time back into the database + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = ?". + " where maintainerId = '?'"; + query_parameters($sQuery, $this->iNotificationLevel, "NOW()", $this->iMaintainerId); + + //TODO: we probably want to copy the mailing list on each of these emails + $sEmail = $oUser->sEmail; + $sEmail.=" cmorgan@alum.wpi.edu"; // FIXME: for debug append my email address + + if($this->iNotificationLevel == 0) + { + if($bDebugOutputEnabled) + echo "At level 0, no warning issued to ".$oUser->sEmail."\n"; + } else + { + if($bDebugOutputEnabled) + { + echo "Email: ".$sEmail."\n"; + echo "Subject: ".$sSubject."\n"; + echo "Msg: ".$sMsg."\n\n"; + } + + mail_appdb($sEmail, $sSubject, $sMsg); + } + } + + // static method called by the cron maintenance script to notify + // maintainers of data pending for their applications and versions + function notifyMaintainersOfQueuedData() + { + // retrieve all of the maintainers + $hResult = maintainer::objectGetEntries(false, false); + + // echo "Processing ".mysql_num_rows($hResult)." maintainers\n"; + + while($oRow = mysql_fetch_object($hResult)) + { + // notify this user, the maintainer, of queued data, if any exists + $oMaintainer = new maintainer(null, $oRow); + $oMaintainer->notifyMaintainerOfQueuedData($this); + } + } } ?> diff --git a/include/testData.php b/include/testData.php index 356ae7c..52b9766 100644 --- a/include/testData.php +++ b/include/testData.php @@ -243,7 +243,7 @@ class testData{ if(!$_SESSION['current']->hasPriv("admin") && !$_SESSION['current']->hasAppVersionModifyPermission($oVersion)) { - return; + return false; } // If we are not in the queue, we can't move the test data out of the queue. @@ -257,7 +257,12 @@ class testData{ // we send an e-mail to interested people $this->mailSubmitter("add"); $this->SendNotificationMail(); + } else + { + return false; } + + return true; } function Reject() diff --git a/tables/maintainers.sql b/tables/maintainers.sql index c6ef4f3..dcedfce 100644 --- a/tables/maintainers.sql +++ b/tables/maintainers.sql @@ -12,13 +12,15 @@ drop table if exists appMaintainers; * for both queued and unqueued maintainers */ create table appMaintainers ( - maintainerId int not null auto_increment, - appId int, - versionId int, - userId int, - maintainReason text, - superMaintainer bool, - submitTime datetime, - queued enum('true','false','rejected') NOT NULL default 'false', + maintainerId int not null auto_increment, + appId int, + versionId int, + userId int, + maintainReason text, + superMaintainer bool, + submitTime datetime, + queued enum('true','false','rejected') NOT NULL default 'false', + notificationLevel int not null default '0', + notificationTime datetime, key(maintainerId) ); diff --git a/unit_test/run_tests.php b/unit_test/run_tests.php index ff8b022..69a5e6c 100644 --- a/unit_test/run_tests.php +++ b/unit_test/run_tests.php @@ -16,6 +16,7 @@ $bTestSuccess = true; include_once("test_user.php"); echo "\n"; + include_once("test_query.php"); echo "\n"; include_once("test_image.php"); diff --git a/unit_test/test_common.php b/unit_test/test_common.php index 2cb34b1..767998c 100644 --- a/unit_test/test_common.php +++ b/unit_test/test_common.php @@ -7,4 +7,27 @@ function test_start($sFunctionName) echo $sFunctionName."() starting\n"; } -?> \ No newline at end of file +// create an application and a version of that application +// return the iVersionId of the created version +function create_version_and_parent_app() +{ + $oApp = new application(); + $oApp->sName = "OM App"; + $oApp->create(); + $oVersion = new version(); + $oVersion->sName = "OM version"; + $oVersion->iAppId = $oApp->iAppId; + $oVersion->create(); + return $oVersion->iVersionId; +} + +// delete a version based on the $iVersionId parameter +// and delete its parent application +function delete_version_and_parent_app($iVersionId) +{ + $oVersion = new version($iVersionId); + $oApp = new application($oVersion->iAppId); + $oApp->delete(); +} + +?> diff --git a/unit_test/test_maintainer.php b/unit_test/test_maintainer.php index 8e58e57..d251ad3 100644 --- a/unit_test/test_maintainer.php +++ b/unit_test/test_maintainer.php @@ -3,6 +3,12 @@ require_once("path.php"); require_once(BASE.'include/maintainer.php'); +// the maintainer notification system tests have been split out +// into another file +include_once("test_maintainer_notify.php"); + + + /* unit tests for maintainer class */ // test that the maintainer count for a given user is accurate for both @@ -569,6 +575,7 @@ function test_maintainer_getMaintainersForAppIdVersionId() return TRUE; } + if(!test_maintainer_getMaintainerCountForUser()) { echo "test_maintainer_getMaintainerCountForUser() failed!\n"; @@ -625,4 +632,13 @@ if(!test_maintainer_getMaintainersForAppIdVersionId()) echo "test_maintainer_getMaintainersForAppIdVersionId() passed\n"; } +if(!test_maintainer_notifyMaintainersOfQueuedData()) +{ + echo "test_maintainer_notifyMaintainersOfQueuedData() failed!\n"; + $bTestSuccess = false; +} else +{ + echo "test_maintainer_notifyMaintainersOfQueuedData() passed\n"; +} + ?> diff --git a/unit_test/test_maintainer_notify.php b/unit_test/test_maintainer_notify.php new file mode 100644 index 0000000..3617e22 --- /dev/null +++ b/unit_test/test_maintainer_notify.php @@ -0,0 +1,697 @@ +__internal_setupQueuedDataForUser($bTestAsMaintainer); + } + + function cleanup() + { + $this->oTestData->delete(); // deleted the created testData + $this->oMaintainer->delete(); // delete the created maintainer entry + // (Should be deleted when the user is deleted) + + // delete the version and its parent application that we created + delete_version_and_parent_app($this->iVersionId); + + // delete the user we created + $this->oUser->delete(); + } + + //FIXME: this should be private when we get php5 + function __internal_setupQueuedDataForUser($bTestAsMaintainer) + { + $bDebugOutputEnabled = false; + + $this->oUser = new User(); + $sUserEmail = "notifyMaintainerUser@somesite.com"; + $sUserPassword = "password"; + + // if we can login as the user, delete the user + if($this->oUser->login($sUserEmail, $sUserPassword) == SUCCESS) + { + // delete the user and create the new user object + $this->oUser->delete(); + $this->oUser = new User(); + } + + // create the user + $iRetval = $this->oUser->create("notifyMaintainerUser@somesite.com", + "password", "testuser1", "0.1.0"); + if($iRetval != SUCCESS) + { + echo "User creation failed, returned $iRetval\n"; + } + + // flag the testing user as the current user + $_SESSION['current'] = $this->oUser; + + // create a fake version + $this->iVersionId = create_version_and_parent_app(); + + // create a queued entry for the user we just created + $this->oTestData = new testData(); + $this->oTestData->iVersionId = $this->iVersionId; + $this->oTestData->shWhatWorks = "nothing"; + $this->oTestData->shWhatDoesnt = "nothing"; + $this->oTestData->shWhatNotTested = "nothing"; + $this->oTestData->sTestedDate = "20070404"; + $this->oTestData->sInstalls = "Yes"; + $this->oTestData->sRuns = "Yes"; + $this->oTestData->sTestedRating = "Gold"; + $this->oTestData->sComments = ""; + if(!$this->oTestData->create()) + { + echo "Failed to create testData\n"; + } + + // make this testData queued, we need to manually override this + // because the user created the application and version and + // because of this the user is allowed to submit unqueued test data + // for an unqueued version that they created + $this->oTestData->ReQueue(); + + // refresh the testdata object now that we've modified its queued status + $this->oTestData = new testData($this->oTestData->iTestingId); + + if($bDebugOutputEnabled) + { + echo "testData:\n"; + print_r($this->oTestData); + } + + // NOTE: we don't unqueue $oTestData because maintainer notification + // only applies to queued testData + + + $this->oVersion = new Version($this->iVersionId); + + // make the user a maintainer of the fake version or application + // depending on whether this user is a maintainer or super maintainer + $this->oMaintainer = new maintainer(); + $this->oMaintainer->iUserId = $this->oUser->iUserId; + $this->oMaintainer->iAppId = $this->oVersion->iAppId; + $this->oMaintainer->sMaintainReason = "for testing"; + if($bTestAsMaintainer) // create a version maintainer entry + { + $this->oMaintainer->bSuperMaintainer = false; + $this->oMaintainer->iVersionId = $this->iVersionId; + } else // create an application maintainer entry, a super maintainer entry + { + $this->oMaintainer->bSuperMaintainer = true; + $this->oMaintainer->iVersionId = 0; + } + + if(!$this->oMaintainer->create()) + { + echo "Failed to create maintainer!\n"; + } + + // notification code checks versions of a super maintainers application + // we must unqueue the version. if the version is queued + // we will only process this queued version during notification + // and will skip over queued entries that depend on this version + if(!$bTestAsMaintainer) + { + $sVersionUnqueue = "update appVersion set queued='?' where versionId = '?'"; + $hResult = query_parameters($sVersionUnqueue, 'false', $this->iVersionId); + } + + // debug printing + if($bDebugOutputEnabled) + { + $sQuery2 = "select * from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery2, $this->oMaintainer->iMaintainerId); + $oObject = mysql_fetch_object($hResult); + print_r($oObject); + } + + // adjust the maintainer submitTime because the oldest entry is + // truncated at the time the user became a maintainer to prevent punishing + // them for signing up for an app that has had queued data for a long time + $iAdjustedTime = strtotime("now") - (100 * 24 * 60 * 60); // 100 days ago + $sQuery = "update appMaintainers set submitTime = '?' where maintainerId = '?'"; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + query_parameters($sQuery, $sDate, $this->oMaintainer->iMaintainerId); + + if($bDebugOutputEnabled) + { + echo "iAdjustedTime for maintainer ".$iAdjustedTime."\n"; + echo "iMaintainerId: ".$this->oMaintainer->iMaintainerId."\n"; + } + + // update our maintainer object to get the new submit time + $this->oMaintainer = new Maintainer($this->oMaintainer->iMaintainerId); + + // echo "new maintainer class:\n"; + // print_r($this->oMaintainer); + } + + // adjust the submission time of the $oTestData object + // to make it appear as if it is $iAgeInSeconds old + function adjustTestDataSubmitTime($iAgeInSeconds) + { + // now adjust the submission time of this entry + // so it is older than iNotificationIntervalDays + // echo "strtotime('now') is ".strtotime("now")."\n"; + // echo "iAgeInSeconds is ".$iAgeInSeconds."\n"; + $iAdjustedTime = strtotime("now") - $iAgeInSeconds; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update testResults set submitTime = '?' where testingId = '?'"; + query_parameters($sQuery, $sDate, $this->oTestData->iTestingId); + + // debug printing + // echo "iAdjustedTime is ".$iAdjustedTime."\n"; + // echo "Original date is: ".date('Y-m-d H:i:s', strtotime("now"))."\n"; + // echo "New date is ".$sDate."\n"; + } + + // returns true if the level is correct, false if not + function checkLevel($iExpectedLevel) + { + $bSuccess = true; + + // create a new maintainer so we can check its level, we COULD use + // the level of the existing $oMaintainer object but we want to + // check both to make sure that the $oMaintainer was updated + // AND that the database was updated + $oMaintainer2 = new maintainer($this->oMaintainer->iMaintainerId); + + // print_r($this->oMaintainer); + + if($this->oMaintainer->iNotificationLevel != $iExpectedLevel) + { + echo "oMaintainer expected iNotificationLevel of ".$iExpectedLevel. + ", actual level is ".$this->oMaintainer->iNotificationLevel."\n"; + $bSuccess = false; + } + + // echo "maintainer2\n"; + // print_r($oMaintainer2); + + if($oMaintainer2->iNotificationLevel != $iExpectedLevel) + { + echo "oMaintainer2 expected iNotificationLevel of ".$iExpectedLevel. + ", actual level is ".$oMaintainer2->iNotificationLevel."\n"; + $bSuccess = false; + } + + return $bSuccess; + } +} + + + +// test a user going from nothing(level 0) to level 1 +function test_maintainer_notifyLevel_0_to_1($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back a little bit + // to be in the level 1 range + $iSecondsOlder = ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test a user going from level 1 to level 2, so the queued time is +// >= (iNotificationIntervalDays * 2) +function test_maintainer_notifyLevel_1_to_2($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = (((iNotificationIntervalDays * 2) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(2); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 2 to 3, where the user will be deleted +function test_maintainer_notifyLevel_2_to_3($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back three intervals + 1 day + // this should be in the level 3 range + $iSecondsOlder = (((iNotificationIntervalDays * 3) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 2 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', ". + "notificationTime = '?' where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + // check to make sure the maintainer doesn't exist + $sQuery = "select count(*) as cnt from appMaintainers where maintainerId = '?'"; + $hResult = query_parameters($sQuery, $oNotifyContainer->oMaintainer->iMaintainerId); + $oRow = mysql_fetch_object($hResult); + if($oRow->cnt != 0) + { + $bSuccess = false; + } + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + // test user going from level 2 to level 1 +function test_maintainer_notifyLevel_2_to_1($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back one interval + 1 day + // this should be in the level 1 range + $iSecondsOlder = ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 2 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 1 to level 0 +function test_maintainer_notifyLevel_1_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // this is only a few seconds old + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test user going from level 2 to level 0 +function test_maintainer_notifyLevel_2_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // this is only a few seconds old + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago + // update the maintainers level to be level 1 to begin with and have them be + // notified iNotificationIntervalDays + 1 ago because we don't check the user + // again unless it has been more thatn iNotificationIntervalDays since + // the last check + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 2; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user that should go from level 1 to level 2 will not do so +// because the last update time is too soon +function test_maintainer_notifyLevel_1_to_2_delay($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = (((iNotificationIntervalDays * 2) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // set the notification time as if we just notified this particular + // maintainer a few seconds ago + $iAdjustedTime = strtotime("now") - 60; + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user with queued items not old enough to cause a transition +// from level 0 to 1 will remain at level 0 +function test_maintainer_notifyLevel_0_to_0($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back two intervals + 1 day + // this should be in the level 2 range + $iSecondsOlder = 60; + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // flag this maintainer as being notified at least a iNotificationIntervalDays + // ago so they should certainly be notified again + $iAdjustedTime = strtotime("now") - ((iNotificationIntervalDays + 1) * 24 * 60 * 60); + $sDate = date('Y-m-d H:i:s', $iAdjustedTime); + $sQuery = "update appMaintainers set notificationLevel = '?', notificationTime = '?' ". + "where maintainerId = '?'"; + $iStartingLevel = 1; + query_parameters($sQuery, $iStartingLevel, $sDate, + $oNotifyContainer->oMaintainer->iMaintainerId); + + // update the maintainer class so our manual changes take effect + $oNotifyContainer->oMaintainer = new Maintainer($oNotifyContainer->oMaintainer->iMaintainerId); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(0); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test that a user with queued data that is really really old will +// only go from level 0 to level 1 +function test_maintainer_notifyLevel_0_to_1_with_old_queued_data($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // adjust the test data submit time back a little bit + // to be in the level 1 range + $iSecondsOlder = (((iNotificationIntervalDays * 5) + 1) * 24 * 60 * 60); + $oNotifyContainer->adjustTestDataSubmitTime($iSecondsOlder); + + // run the notification code to update the users level + $oNotifyContainer->oMaintainer->notifyMaintainerOfQueuedData(); + + $bSuccess = $oNotifyContainer->checkLevel(1); + if(!$bSuccess) + echo "checkLevel() failed\n"; + + // cleanup the things we created during the notification test + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +function test_maintainer_notifyLevel_starts_at_zero($bTestAsMaintainer) +{ + echo __FUNCTION__."\n"; + + $bSuccess = true; // default to success + + $oNotifyContainer = new notifyContainer($bTestAsMaintainer); + + // see if our notification level is zero + if($oNotifyContainer->oMaintainer->iNotificationLevel != 0) + { + $bSuccess = false; + } + + $oNotifyContainer->cleanup(); + + return $bSuccess; +} + +// test maintainer::notifyMaintainerOfQueuedData() in various +// potential situations +// $bTestAsMaintainer == true - the user being tested is a normal maintainer +// $bTestAsMaintainer == false - the user being tested is a super maintainer +function _test_maintainer_notifyMaintainersOfQueuedData($bTestAsMaintainer) +{ + $bSuccess = true; // default to success + + echo __FUNCTION__."\n"; + + $sFunction = "test_maintainer_notifyLevel_0_to_1"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_2"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_3"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_1"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_2_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_1_to_2_delay"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_0_to_0"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_0_to_1_with_old_queued_data"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + $sFunction = "test_maintainer_notifyLevel_starts_at_zero"; + if(!$sFunction($bTestAsMaintainer)) + { + echo $sFunction." failed!\n"; + $bSuccess = false; + } + + return $bSuccess; +} + + +// test maintainer::notifyMaintainerOfQueuedData() in various +// potential situations +// NOTE: we test one as a normal maintainer and once as a super maintainer +function test_maintainer_notifyMaintainersOfQueuedData() +{ + $bSuccess = true; + + echo "Testing as maintainer\n"; + if(!_test_maintainer_notifyMaintainersOfQueuedData(true)) + { + echo "Maintainer test failed!\n"; + $bSuccess = false; + } + + echo "\n\nTesting as super maintainer\n"; + if(!_test_maintainer_notifyMaintainersOfQueuedData(false)) + { + echo "Super maintainer test failed!\n"; + $bSuccess = false; + } + + return $bSuccess; +} +?> diff --git a/unit_test/test_om_objects.php b/unit_test/test_om_objects.php index cd0b2f6..f9b332c 100644 --- a/unit_test/test_om_objects.php +++ b/unit_test/test_om_objects.php @@ -159,10 +159,10 @@ function cleanup($oObject) case "maintainer": case "screenshot": case "testData": - delete_parent($oObject->iVersionId); + delete_version_and_parent_app($oObject->iVersionId); break; case "testData_queue": - delete_parent($oObject->oTestData->iVersionId); + delete_version_and_parent_app($oObject->oTestData->iVersionId); break; case "version": $oApp = new application($oObject->iAppId); @@ -175,25 +175,6 @@ function cleanup($oObject) } } -function create_version() -{ - $oApp = new application(); - $oApp->sName = "OM App"; - $oApp->create(); - $oVersion = new version(); - $oVersion->sName = "OM version"; - $oVersion->iAppId = $oApp->iAppId; - $oVersion->create(); - return $oVersion->iVersionId; -} - -function delete_parent($iVersionId) -{ - $oVersion = new version($iVersionId); - $oApp = new application($oVersion->iAppId); - $oApp->delete(); -} - function create_object($sClassName, $oUser) { $oUser->addPriv("admin"); @@ -208,10 +189,10 @@ function create_object($sClassName, $oUser) case "downloadurl": $oTestObject->sUrl = "http://appdb.winehq.org/"; $oTestObject->sDescription = "DANGER"; - $oTestObject->iVersionId = create_version(); + $oTestObject->iVersionId = create_version_and_parent_app(); break; case "maintainer": - $oVersion = new version(create_version()); + $oVersion = new version(create_version_and_parent_app()); $oTestObject->iUserId = $oUser->iUserId; $oTestObject->iAppId = $oVersion->iAppId; $oTestObject->iVersionId = $oVersion->iVersionId; @@ -219,10 +200,10 @@ function create_object($sClassName, $oUser) break; case "screenshot": case "testData": - $oTestObject->iVersionId = create_version(); + $oTestObject->iVersionId = create_version_and_parent_app(); break; case "testData_queue": - $oTestObject->oTestData->iVersionId = create_version(); + $oTestObject->oTestData->iVersionId = create_version_and_parent_app(); break; case "version": $oApp = new application();