Reorganize system folder
This commit is contained in:
parent
2c20d3b83e
commit
327ba4bf6f
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/sys/db/.travis.yml
|
||||
/sys/db/docs/*
|
||||
/sys/db/phpdoc.dist.xml
|
||||
/sys/db/README.md
|
||||
/sys/db/tests/*
|
@ -8,9 +8,9 @@
|
||||
<p>Backtrace: </p>
|
||||
<?php foreach($exception->getTrace() as $error): ?>
|
||||
|
||||
<?php if(isset($error['file']) && ! stristr($error['file'], SYS_PATH)): ?>
|
||||
<?php if (isset($error['file']) && ! stristr($error['file'], MM_SYS_PATH)): ?>
|
||||
<p style="margin-left:10px">
|
||||
File: <?= str_replace(BASE_PATH, "", $error['file']) ?><br />
|
||||
File: <?= str_replace(MM_BASE_PATH, "", $error['file']) ?><br />
|
||||
Line: <?= $error['line'] ?><br />
|
||||
Function: <?= $error['function'] ?>
|
||||
</p>
|
||||
|
235
docs/classes.svg
235
docs/classes.svg
@ -4,74 +4,74 @@
|
||||
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="874pt" height="1192pt"
|
||||
viewBox="0.00 0.00 874.00 1192.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 1188)">
|
||||
<svg width="874pt" height="1246pt"
|
||||
viewBox="0.00 0.00 874.00 1246.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 1242)">
|
||||
<title>G</title>
|
||||
<polygon fill="white" stroke="white" points="-4,5 -4,-1188 871,-1188 871,5 -4,5"/>
|
||||
<polygon fill="white" stroke="white" points="-4,5 -4,-1242 871,-1242 871,5 -4,5"/>
|
||||
<g id="graph2" class="cluster"><title>cluster_default</title>
|
||||
<polyline fill="none" stroke="none" points="218,-44 846,-44 "/>
|
||||
<path fill="none" stroke="none" d="M846,-44C852,-44 858,-50 858,-56"/>
|
||||
<polyline fill="none" stroke="none" points="858,-56 858,-1164 "/>
|
||||
<path fill="none" stroke="none" d="M858,-1164C858,-1170 852,-1176 846,-1176"/>
|
||||
<polyline fill="none" stroke="none" points="846,-1176 218,-1176 "/>
|
||||
<path fill="none" stroke="none" d="M218,-1176C212,-1176 206,-1170 206,-1164"/>
|
||||
<polyline fill="none" stroke="none" points="206,-1164 206,-56 "/>
|
||||
<polyline fill="none" stroke="none" points="858,-56 858,-1218 "/>
|
||||
<path fill="none" stroke="none" d="M858,-1218C858,-1224 852,-1230 846,-1230"/>
|
||||
<polyline fill="none" stroke="none" points="846,-1230 218,-1230 "/>
|
||||
<path fill="none" stroke="none" d="M218,-1230C212,-1230 206,-1224 206,-1218"/>
|
||||
<polyline fill="none" stroke="none" points="206,-1218 206,-56 "/>
|
||||
<path fill="none" stroke="none" d="M206,-56C206,-50 212,-44 218,-44"/>
|
||||
</g>
|
||||
<!-- \\DB_Reg -->
|
||||
<g id="node2" class="node"><title>\\DB_Reg</title>
|
||||
<a xlink:href="sys.db.classes.db_reg.html" xlink:title="DB_Reg" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="819,-1168 763,-1168 763,-1132 819,-1132 819,-1168"/>
|
||||
<text text-anchor="middle" x="791" y="-1146.6" font-family="Courier,monospace" font-size="11.00">DB_Reg</text>
|
||||
<polygon fill="none" stroke="black" points="819,-1222 763,-1222 763,-1186 819,-1186 819,-1222"/>
|
||||
<text text-anchor="middle" x="791" y="-1200.6" font-family="Courier,monospace" font-size="11.00">DB_Reg</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\Settings -->
|
||||
<g id="node3" class="node"><title>\\Settings</title>
|
||||
<a xlink:href="sys.db.classes.settings.html" xlink:title="Settings" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="826,-1114 756,-1114 756,-1078 826,-1078 826,-1114"/>
|
||||
<text text-anchor="middle" x="791" y="-1092.6" font-family="Courier,monospace" font-size="11.00">Settings</text>
|
||||
<polygon fill="none" stroke="black" points="826,-1168 756,-1168 756,-1132 826,-1132 826,-1168"/>
|
||||
<text text-anchor="middle" x="791" y="-1146.6" font-family="Courier,monospace" font-size="11.00">Settings</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\DB_SQL -->
|
||||
<g id="node4" class="node"><title>\\DB_SQL</title>
|
||||
<a xlink:href="sys.db.classes.db_sql.html" xlink:title="«abstract»<br/>DB_SQL" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="617,-682 533,-682 533,-646 617,-646 617,-682"/>
|
||||
<text text-anchor="start" x="541" y="-669.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="554.5" y="-656.233" font-family="Courier,monospace" font-size="11.00">DB_SQL</text>
|
||||
<polygon fill="none" stroke="black" points="617,-736 533,-736 533,-700 617,-700 617,-736"/>
|
||||
<text text-anchor="start" x="541" y="-723.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="554.5" y="-710.233" font-family="Courier,monospace" font-size="11.00">DB_SQL</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\DB_PDO -->
|
||||
<g id="node5" class="node"><title>\\DB_PDO</title>
|
||||
<a xlink:href="sys.db.classes.db_pdo.html" xlink:title="«abstract»<br/>DB_PDO" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="617,-223 533,-223 533,-187 617,-187 617,-223"/>
|
||||
<text text-anchor="start" x="541" y="-210.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="554.5" y="-197.233" font-family="Courier,monospace" font-size="11.00">DB_PDO</text>
|
||||
<polygon fill="none" stroke="black" points="617,-277 533,-277 533,-241 617,-241 617,-277"/>
|
||||
<text text-anchor="start" x="541" y="-264.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="554.5" y="-251.233" font-family="Courier,monospace" font-size="11.00">DB_PDO</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\PDO -->
|
||||
<g id="node34" class="node"><title>\\PDO</title>
|
||||
<g id="node35" class="node"><title>\\PDO</title>
|
||||
<ellipse fill="none" stroke="black" cx="379" cy="-18" rx="35.0527" ry="18"/>
|
||||
<text text-anchor="middle" x="379" y="-13.4" font-family="Times Roman,serif" font-size="14.00" fill="gray">\PDO</text>
|
||||
</g>
|
||||
<!-- \\DB_PDO->\\PDO -->
|
||||
<g id="edge3" class="edge"><title>\\DB_PDO->\\PDO</title>
|
||||
<path fill="none" stroke="black" d="M532.431,-201.202C517.741,-198.13 501.983,-192.666 490,-183 434.617,-138.323 467.115,-91.488 418,-40 416.783,-38.7238 415.475,-37.5011 414.102,-36.3323"/>
|
||||
<polygon fill="none" stroke="black" points="415.855,-33.2795 405.708,-30.2321 411.74,-38.9422 415.855,-33.2795"/>
|
||||
<path fill="none" stroke="black" d="M532.23,-256.037C517.348,-253.062 501.515,-247.447 490,-237 420.961,-174.361 478.324,-111.07 418,-40 416.859,-38.6554 415.613,-37.3763 414.291,-36.1617"/>
|
||||
<polygon fill="none" stroke="black" points="416.149,-33.1773 406.073,-29.9031 411.908,-38.7463 416.149,-33.1773"/>
|
||||
</g>
|
||||
<!-- \\Query_Builder -->
|
||||
<g id="node6" class="node"><title>\\Query_Builder</title>
|
||||
<a xlink:href="sys.db.classes.query_builder.html" xlink:title="Query_Builder" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="627,-466 523,-466 523,-430 627,-430 627,-466"/>
|
||||
<text text-anchor="middle" x="575" y="-444.6" font-family="Courier,monospace" font-size="11.00">Query_Builder</text>
|
||||
<polygon fill="none" stroke="black" points="627,-520 523,-520 523,-484 627,-484 627,-520"/>
|
||||
<text text-anchor="middle" x="575" y="-498.6" font-family="Courier,monospace" font-size="11.00">Query_Builder</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\DB_Util -->
|
||||
<g id="node7" class="node"><title>\\DB_Util</title>
|
||||
<a xlink:href="sys.db.classes.db_util.html" xlink:title="«abstract»<br/>DB_Util" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="617,-952 533,-952 533,-916 617,-916 617,-952"/>
|
||||
<text text-anchor="start" x="541" y="-939.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="551" y="-926.233" font-family="Courier,monospace" font-size="11.00">DB_Util</text>
|
||||
<polygon fill="none" stroke="black" points="617,-1006 533,-1006 533,-970 617,-970 617,-1006"/>
|
||||
<text text-anchor="start" x="541" y="-993.433" font-family="Courier,monospace" font-size="11.00">«abstract»</text>
|
||||
<text text-anchor="start" x="551" y="-980.233" font-family="Courier,monospace" font-size="11.00">DB_Util</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\PgSQL_SQL -->
|
||||
@ -83,8 +83,8 @@
|
||||
</g>
|
||||
<!-- \\PgSQL_SQL->\\DB_SQL -->
|
||||
<g id="edge5" class="edge"><title>\\PgSQL_SQL->\\DB_SQL</title>
|
||||
<path fill="none" stroke="black" d="M752.384,-708.346C717.629,-699.657 666.251,-686.813 627.723,-677.181"/>
|
||||
<polygon fill="none" stroke="black" points="628.273,-673.711 617.723,-674.681 626.576,-680.502 628.273,-673.711"/>
|
||||
<path fill="none" stroke="black" d="M752.384,-718C717.629,-718 666.251,-718 627.723,-718"/>
|
||||
<polygon fill="none" stroke="black" points="627.723,-714.5 617.723,-718 627.723,-721.5 627.723,-714.5"/>
|
||||
</g>
|
||||
<!-- \\PgSQL_Util -->
|
||||
<g id="node9" class="node"><title>\\PgSQL_Util</title>
|
||||
@ -95,20 +95,20 @@
|
||||
</g>
|
||||
<!-- \\PgSQL_Util->\\DB_Util -->
|
||||
<g id="edge7" class="edge"><title>\\PgSQL_Util->\\DB_Util</title>
|
||||
<path fill="none" stroke="black" d="M748.84,-977.46C714.276,-968.819 665.162,-956.54 627.95,-947.237"/>
|
||||
<polygon fill="none" stroke="black" points="628.342,-943.728 617.792,-944.698 626.644,-950.519 628.342,-943.728"/>
|
||||
<path fill="none" stroke="black" d="M748.84,-988C714.276,-988 665.162,-988 627.95,-988"/>
|
||||
<polygon fill="none" stroke="black" points="627.792,-984.5 617.792,-988 627.792,-991.5 627.792,-984.5"/>
|
||||
</g>
|
||||
<!-- \\PgSQL -->
|
||||
<g id="node10" class="node"><title>\\PgSQL</title>
|
||||
<a xlink:href="sys.db.drivers.pgsql.pgsql_driver.html" xlink:title="PgSQL" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="818,-196 764,-196 764,-160 818,-160 818,-196"/>
|
||||
<text text-anchor="middle" x="791" y="-174.6" font-family="Courier,monospace" font-size="11.00">PgSQL</text>
|
||||
<polygon fill="none" stroke="black" points="818,-142 764,-142 764,-106 818,-106 818,-142"/>
|
||||
<text text-anchor="middle" x="791" y="-120.6" font-family="Courier,monospace" font-size="11.00">PgSQL</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\PgSQL->\\DB_PDO -->
|
||||
<g id="edge9" class="edge"><title>\\PgSQL->\\DB_PDO</title>
|
||||
<path fill="none" stroke="black" d="M763.643,-181.42C729.593,-185.676 670.693,-193.038 627.747,-198.407"/>
|
||||
<polygon fill="none" stroke="black" points="627.236,-194.943 617.747,-199.657 628.104,-201.889 627.236,-194.943"/>
|
||||
<path fill="none" stroke="black" d="M763.749,-133.489C753.242,-137.886 741.495,-143.76 732,-151 692.36,-181.227 702.141,-210.372 660,-237 650.233,-243.172 638.798,-247.617 627.539,-250.818"/>
|
||||
<polygon fill="none" stroke="black" points="626.559,-247.456 617.736,-253.322 628.292,-254.238 626.559,-247.456"/>
|
||||
</g>
|
||||
<!-- \\ODBC_Util -->
|
||||
<g id="node11" class="node"><title>\\ODBC_Util</title>
|
||||
@ -119,8 +119,8 @@
|
||||
</g>
|
||||
<!-- \\ODBC_Util->\\DB_Util -->
|
||||
<g id="edge11" class="edge"><title>\\ODBC_Util->\\DB_Util</title>
|
||||
<path fill="none" stroke="black" d="M752.384,-934C717.629,-934 666.251,-934 627.723,-934"/>
|
||||
<polygon fill="none" stroke="black" points="627.723,-930.5 617.723,-934 627.723,-937.5 627.723,-930.5"/>
|
||||
<path fill="none" stroke="black" d="M752.384,-943.654C717.629,-952.343 666.251,-965.187 627.723,-974.819"/>
|
||||
<polygon fill="none" stroke="black" points="626.576,-971.498 617.723,-977.319 628.273,-978.289 626.576,-971.498"/>
|
||||
</g>
|
||||
<!-- \\ODBC_SQL -->
|
||||
<g id="node12" class="node"><title>\\ODBC_SQL</title>
|
||||
@ -131,20 +131,20 @@
|
||||
</g>
|
||||
<!-- \\ODBC_SQL->\\DB_SQL -->
|
||||
<g id="edge13" class="edge"><title>\\ODBC_SQL->\\DB_SQL</title>
|
||||
<path fill="none" stroke="black" d="M755.815,-664C721.064,-664 667.487,-664 627.664,-664"/>
|
||||
<polygon fill="none" stroke="black" points="627.598,-660.5 617.598,-664 627.598,-667.5 627.598,-660.5"/>
|
||||
<path fill="none" stroke="black" d="M755.815,-672.796C720.991,-681.502 667.26,-694.935 627.41,-704.897"/>
|
||||
<polygon fill="none" stroke="black" points="626.451,-701.53 617.598,-707.35 628.148,-708.321 626.451,-701.53"/>
|
||||
</g>
|
||||
<!-- \\ODBC -->
|
||||
<g id="node13" class="node"><title>\\ODBC</title>
|
||||
<a xlink:href="sys.db.drivers.odbc.odbc_driver.html" xlink:title="ODBC" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="818,-142 764,-142 764,-106 818,-106 818,-142"/>
|
||||
<text text-anchor="middle" x="791" y="-120.6" font-family="Courier,monospace" font-size="11.00">ODBC</text>
|
||||
<polygon fill="none" stroke="black" points="818,-412 764,-412 764,-376 818,-376 818,-412"/>
|
||||
<text text-anchor="middle" x="791" y="-390.6" font-family="Courier,monospace" font-size="11.00">ODBC</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\ODBC->\\DB_PDO -->
|
||||
<g id="edge15" class="edge"><title>\\ODBC->\\DB_PDO</title>
|
||||
<path fill="none" stroke="black" d="M763.695,-136.44C726.868,-153.197 665.25,-181.153 660,-183 649.651,-186.64 638.403,-189.972 627.58,-192.882"/>
|
||||
<polygon fill="none" stroke="black" points="626.591,-189.523 617.797,-195.432 628.356,-196.296 626.591,-189.523"/>
|
||||
<path fill="none" stroke="black" d="M763.782,-382.728C753.615,-378.212 742.093,-372.723 732,-367 686.756,-341.342 637.869,-306.466 606.878,-283.371"/>
|
||||
<polygon fill="none" stroke="black" points="608.731,-280.385 598.63,-277.186 604.531,-285.985 608.731,-280.385"/>
|
||||
</g>
|
||||
<!-- \\MySQL_Util -->
|
||||
<g id="node14" class="node"><title>\\MySQL_Util</title>
|
||||
@ -155,8 +155,8 @@
|
||||
</g>
|
||||
<!-- \\MySQL_Util->\\DB_Util -->
|
||||
<g id="edge17" class="edge"><title>\\MySQL_Util->\\DB_Util</title>
|
||||
<path fill="none" stroke="black" d="M748.325,-890.669C713.712,-899.322 664.759,-911.56 627.701,-920.825"/>
|
||||
<polygon fill="none" stroke="black" points="626.439,-917.533 617.586,-923.354 628.136,-924.324 626.439,-917.533"/>
|
||||
<path fill="none" stroke="black" d="M750.892,-898.047C744.548,-900.99 738.078,-904.043 732,-907 692.965,-925.988 649.105,-948.738 617.686,-965.287"/>
|
||||
<polygon fill="none" stroke="black" points="615.972,-962.234 608.762,-969.997 619.24,-968.425 615.972,-962.234"/>
|
||||
</g>
|
||||
<!-- \\MySQL -->
|
||||
<g id="node15" class="node"><title>\\MySQL</title>
|
||||
@ -167,8 +167,8 @@
|
||||
</g>
|
||||
<!-- \\MySQL->\\DB_PDO -->
|
||||
<g id="edge19" class="edge"><title>\\MySQL->\\DB_PDO</title>
|
||||
<path fill="none" stroke="black" d="M763.782,-328.728C753.615,-324.212 742.093,-318.723 732,-313 686.756,-287.342 637.869,-252.466 606.878,-229.371"/>
|
||||
<polygon fill="none" stroke="black" points="608.731,-226.385 598.63,-223.186 604.531,-231.985 608.731,-226.385"/>
|
||||
<path fill="none" stroke="black" d="M763.643,-329.741C729.449,-316.918 670.196,-294.699 627.205,-278.577"/>
|
||||
<polygon fill="none" stroke="black" points="628.339,-275.264 617.747,-275.03 625.882,-281.819 628.339,-275.264"/>
|
||||
</g>
|
||||
<!-- \\MySQL_SQL -->
|
||||
<g id="node16" class="node"><title>\\MySQL_SQL</title>
|
||||
@ -179,20 +179,20 @@
|
||||
</g>
|
||||
<!-- \\MySQL_SQL->\\DB_SQL -->
|
||||
<g id="edge21" class="edge"><title>\\MySQL_SQL->\\DB_SQL</title>
|
||||
<path fill="none" stroke="black" d="M751.884,-619.779C717.065,-628.484 665.851,-641.287 627.48,-650.88"/>
|
||||
<polygon fill="none" stroke="black" points="626.374,-647.549 617.522,-653.37 628.072,-654.34 626.374,-647.549"/>
|
||||
<path fill="none" stroke="black" d="M751.843,-627.606C745.196,-630.684 738.382,-633.896 732,-637 692.965,-655.988 649.105,-678.738 617.686,-695.287"/>
|
||||
<polygon fill="none" stroke="black" points="615.972,-692.234 608.762,-699.997 619.24,-698.425 615.972,-692.234"/>
|
||||
</g>
|
||||
<!-- \\SQLite_Util -->
|
||||
<g id="node17" class="node"><title>\\SQLite_Util</title>
|
||||
<a xlink:href="sys.db.drivers.sqlite.sqlite_util.html" xlink:title="SQLite_Util" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="836,-844 746,-844 746,-808 836,-808 836,-844"/>
|
||||
<text text-anchor="middle" x="791" y="-822.6" font-family="Courier,monospace" font-size="11.00">SQLite_Util</text>
|
||||
<polygon fill="none" stroke="black" points="836,-1114 746,-1114 746,-1078 836,-1078 836,-1114"/>
|
||||
<text text-anchor="middle" x="791" y="-1092.6" font-family="Courier,monospace" font-size="11.00">SQLite_Util</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\SQLite_Util->\\DB_Util -->
|
||||
<g id="edge23" class="edge"><title>\\SQLite_Util->\\DB_Util</title>
|
||||
<path fill="none" stroke="black" d="M750.892,-844.047C744.548,-846.99 738.078,-850.043 732,-853 692.965,-871.988 649.105,-894.738 617.686,-911.287"/>
|
||||
<polygon fill="none" stroke="black" points="615.972,-908.234 608.762,-915.997 619.24,-914.425 615.972,-908.234"/>
|
||||
<path fill="none" stroke="black" d="M750.892,-1077.95C744.548,-1075.01 738.078,-1071.96 732,-1069 692.965,-1050.01 649.105,-1027.26 617.686,-1010.71"/>
|
||||
<polygon fill="none" stroke="black" points="619.24,-1007.58 608.762,-1006 615.972,-1013.77 619.24,-1007.58"/>
|
||||
</g>
|
||||
<!-- \\SQLite -->
|
||||
<g id="node18" class="node"><title>\\SQLite</title>
|
||||
@ -203,20 +203,20 @@
|
||||
</g>
|
||||
<!-- \\SQLite->\\DB_PDO -->
|
||||
<g id="edge25" class="edge"><title>\\SQLite->\\DB_PDO</title>
|
||||
<path fill="none" stroke="black" d="M762.317,-275.244C727.929,-262.348 669.629,-240.486 627.188,-224.57"/>
|
||||
<polygon fill="none" stroke="black" points="628.169,-221.2 617.577,-220.966 625.711,-227.755 628.169,-221.2"/>
|
||||
<path fill="none" stroke="black" d="M762.317,-282.415C728.073,-278.134 670.12,-270.89 627.724,-265.591"/>
|
||||
<polygon fill="none" stroke="black" points="627.934,-262.09 617.577,-264.322 627.066,-269.036 627.934,-262.09"/>
|
||||
</g>
|
||||
<!-- \\SQLite_SQL -->
|
||||
<g id="node19" class="node"><title>\\SQLite_SQL</title>
|
||||
<a xlink:href="sys.db.drivers.sqlite.sqlite_sql.html" xlink:title="SQLite_SQL" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="833,-574 749,-574 749,-538 833,-538 833,-574"/>
|
||||
<text text-anchor="middle" x="791" y="-552.6" font-family="Courier,monospace" font-size="11.00">SQLite_SQL</text>
|
||||
<polygon fill="none" stroke="black" points="833,-844 749,-844 749,-808 833,-808 833,-844"/>
|
||||
<text text-anchor="middle" x="791" y="-822.6" font-family="Courier,monospace" font-size="11.00">SQLite_SQL</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\SQLite_SQL->\\DB_SQL -->
|
||||
<g id="edge27" class="edge"><title>\\SQLite_SQL->\\DB_SQL</title>
|
||||
<path fill="none" stroke="black" d="M750.892,-574.047C744.548,-576.99 738.078,-580.043 732,-583 692.965,-601.988 649.105,-624.738 617.686,-641.287"/>
|
||||
<polygon fill="none" stroke="black" points="615.972,-638.234 608.762,-645.997 619.24,-644.425 615.972,-638.234"/>
|
||||
<path fill="none" stroke="black" d="M750.892,-807.953C744.548,-805.01 738.078,-801.957 732,-799 692.965,-780.012 649.105,-757.262 617.686,-740.713"/>
|
||||
<polygon fill="none" stroke="black" points="619.24,-737.575 608.762,-736.003 615.972,-743.766 619.24,-737.575"/>
|
||||
</g>
|
||||
<!-- \\Firebird_SQL -->
|
||||
<g id="node20" class="node"><title>\\Firebird_SQL</title>
|
||||
@ -227,8 +227,8 @@
|
||||
</g>
|
||||
<!-- \\Firebird_SQL->\\DB_SQL -->
|
||||
<g id="edge29" class="edge"><title>\\Firebird_SQL->\\DB_SQL</title>
|
||||
<path fill="none" stroke="black" d="M750.892,-753.953C744.548,-751.01 738.078,-747.957 732,-745 692.965,-726.012 649.105,-703.262 617.686,-686.713"/>
|
||||
<polygon fill="none" stroke="black" points="619.24,-683.575 608.762,-682.003 615.972,-689.766 619.24,-683.575"/>
|
||||
<path fill="none" stroke="black" d="M742.256,-759.814C708.168,-751.292 662.673,-739.918 627.738,-731.185"/>
|
||||
<polygon fill="none" stroke="black" points="628.273,-727.711 617.723,-728.681 626.575,-734.502 628.273,-727.711"/>
|
||||
</g>
|
||||
<!-- \\Firebird_Result -->
|
||||
<g id="node21" class="node"><title>\\Firebird_Result</title>
|
||||
@ -238,7 +238,7 @@
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\PDOStatement -->
|
||||
<g id="node49" class="node"><title>\\PDOStatement</title>
|
||||
<g id="node50" class="node"><title>\\PDOStatement</title>
|
||||
<ellipse fill="none" stroke="black" cx="575" cy="-18" rx="85.1942" ry="18"/>
|
||||
<text text-anchor="middle" x="575" y="-13.4" font-family="Times Roman,serif" font-size="14.00" fill="gray">\PDOStatement</text>
|
||||
</g>
|
||||
@ -256,8 +256,8 @@
|
||||
</g>
|
||||
<!-- \\Firebird->\\DB_PDO -->
|
||||
<g id="edge33" class="edge"><title>\\Firebird->\\DB_PDO</title>
|
||||
<path fill="none" stroke="black" d="M755.815,-227.602C721.064,-223.258 667.487,-216.561 627.664,-211.583"/>
|
||||
<polygon fill="none" stroke="black" points="627.955,-208.092 617.598,-210.325 627.087,-215.038 627.955,-208.092"/>
|
||||
<path fill="none" stroke="black" d="M755.815,-236.398C721.064,-240.742 667.487,-247.439 627.664,-252.417"/>
|
||||
<polygon fill="none" stroke="black" points="627.087,-248.962 617.598,-253.675 627.955,-255.908 627.087,-248.962"/>
|
||||
</g>
|
||||
<!-- \\Firebird_Util -->
|
||||
<g id="node23" class="node"><title>\\Firebird_Util</title>
|
||||
@ -268,121 +268,128 @@
|
||||
</g>
|
||||
<!-- \\Firebird_Util->\\DB_Util -->
|
||||
<g id="edge35" class="edge"><title>\\Firebird_Util->\\DB_Util</title>
|
||||
<path fill="none" stroke="black" d="M750.892,-1023.95C744.548,-1021.01 738.078,-1017.96 732,-1015 692.965,-996.012 649.105,-973.262 617.686,-956.713"/>
|
||||
<polygon fill="none" stroke="black" points="619.24,-953.575 608.762,-952.003 615.972,-959.766 619.24,-953.575"/>
|
||||
<path fill="none" stroke="black" d="M738.988,-1029C705.13,-1020.53 661.125,-1009.53 627.225,-1001.06"/>
|
||||
<polygon fill="none" stroke="black" points="628.051,-997.655 617.5,-998.625 626.353,-1004.45 628.051,-997.655"/>
|
||||
</g>
|
||||
<!-- \\MM_Model -->
|
||||
<g id="node24" class="node"><title>\\MM_Model</title>
|
||||
<a xlink:href="sys.model.html" xlink:title="MM_Model" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="610,-520 540,-520 540,-484 610,-484 610,-520"/>
|
||||
<text text-anchor="middle" x="575" y="-498.6" font-family="Courier,monospace" font-size="11.00">MM_Model</text>
|
||||
<a xlink:href="sys.core.model.html" xlink:title="MM_Model" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="610,-574 540,-574 540,-538 610,-538 610,-574"/>
|
||||
<text text-anchor="middle" x="575" y="-552.6" font-family="Courier,monospace" font-size="11.00">MM_Model</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\miniMVC -->
|
||||
<g id="node27" class="node"><title>\\miniMVC</title>
|
||||
<a xlink:href="sys.miniMVC.html" xlink:title="miniMVC" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="411,-466 347,-466 347,-430 411,-430 411,-466"/>
|
||||
<text text-anchor="middle" x="379" y="-444.6" font-family="Courier,monospace" font-size="11.00">miniMVC</text>
|
||||
<a xlink:href="sys.core.miniMVC.html" xlink:title="miniMVC" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="411,-520 347,-520 347,-484 411,-484 411,-520"/>
|
||||
<text text-anchor="middle" x="379" y="-498.6" font-family="Courier,monospace" font-size="11.00">miniMVC</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\MM_Model->\\miniMVC -->
|
||||
<g id="edge37" class="edge"><title>\\MM_Model->\\miniMVC</title>
|
||||
<path fill="none" stroke="black" d="M539.051,-492.096C505.958,-482.978 456.829,-469.443 421.74,-459.775"/>
|
||||
<polygon fill="none" stroke="black" points="422.359,-456.316 411.789,-457.034 420.5,-463.064 422.359,-456.316"/>
|
||||
<path fill="none" stroke="black" d="M539.051,-546.096C505.958,-536.978 456.829,-523.443 421.74,-513.775"/>
|
||||
<polygon fill="none" stroke="black" points="422.359,-510.316 411.789,-511.034 420.5,-517.064 422.359,-510.316"/>
|
||||
</g>
|
||||
<!-- \\DB -->
|
||||
<g id="node25" class="node"><title>\\DB</title>
|
||||
<a xlink:href="sys.db.html" xlink:title="DB" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="818,-466 764,-466 764,-430 818,-430 818,-466"/>
|
||||
<text text-anchor="middle" x="791" y="-444.6" font-family="Courier,monospace" font-size="11.00">DB</text>
|
||||
<a xlink:href="sys.core.db.html" xlink:title="DB" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="818,-520 764,-520 764,-484 818,-484 818,-520"/>
|
||||
<text text-anchor="middle" x="791" y="-498.6" font-family="Courier,monospace" font-size="11.00">DB</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\DB->\\Query_Builder -->
|
||||
<g id="edge39" class="edge"><title>\\DB->\\Query_Builder</title>
|
||||
<path fill="none" stroke="black" d="M763.643,-448C732.077,-448 679.154,-448 637.385,-448"/>
|
||||
<polygon fill="none" stroke="black" points="637.298,-444.5 627.298,-448 637.298,-451.5 637.298,-444.5"/>
|
||||
<path fill="none" stroke="black" d="M763.643,-502C732.077,-502 679.154,-502 637.385,-502"/>
|
||||
<polygon fill="none" stroke="black" points="637.298,-498.5 627.298,-502 637.298,-505.5 637.298,-498.5"/>
|
||||
</g>
|
||||
<!-- \\MM -->
|
||||
<g id="node26" class="node"><title>\\MM</title>
|
||||
<a xlink:href="sys.miniMVC.html" xlink:title="MM" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="268,-520 214,-520 214,-484 268,-484 268,-520"/>
|
||||
<text text-anchor="middle" x="241" y="-498.6" font-family="Courier,monospace" font-size="11.00">MM</text>
|
||||
<a xlink:href="sys.core.miniMVC.html" xlink:title="MM" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="268,-574 214,-574 214,-538 268,-538 268,-574"/>
|
||||
<text text-anchor="middle" x="241" y="-552.6" font-family="Courier,monospace" font-size="11.00">MM</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\ArrayObject -->
|
||||
<g id="node55" class="node"><title>\\ArrayObject</title>
|
||||
<ellipse fill="none" stroke="black" cx="71" cy="-502" rx="71.107" ry="18"/>
|
||||
<text text-anchor="middle" x="71" y="-497.4" font-family="Times Roman,serif" font-size="14.00" fill="gray">\ArrayObject</text>
|
||||
<g id="node56" class="node"><title>\\ArrayObject</title>
|
||||
<ellipse fill="none" stroke="black" cx="71" cy="-556" rx="71.107" ry="18"/>
|
||||
<text text-anchor="middle" x="71" y="-551.4" font-family="Times Roman,serif" font-size="14.00" fill="gray">\ArrayObject</text>
|
||||
</g>
|
||||
<!-- \\MM->\\ArrayObject -->
|
||||
<g id="edge41" class="edge"><title>\\MM->\\ArrayObject</title>
|
||||
<path fill="none" stroke="black" d="M213.687,-502C196.92,-502 174.483,-502 152.374,-502"/>
|
||||
<polygon fill="none" stroke="black" points="152.26,-498.5 142.26,-502 152.26,-505.5 152.26,-498.5"/>
|
||||
<path fill="none" stroke="black" d="M213.687,-556C196.92,-556 174.483,-556 152.374,-556"/>
|
||||
<polygon fill="none" stroke="black" points="152.26,-552.5 142.26,-556 152.26,-559.5 152.26,-552.5"/>
|
||||
</g>
|
||||
<!-- \\miniMVC->\\MM -->
|
||||
<g id="edge43" class="edge"><title>\\miniMVC->\\MM</title>
|
||||
<path fill="none" stroke="black" d="M346.296,-460.797C325.699,-468.857 299.069,-479.277 277.744,-487.622"/>
|
||||
<polygon fill="none" stroke="black" points="276.397,-484.391 268.36,-491.294 278.948,-490.909 276.397,-484.391"/>
|
||||
<path fill="none" stroke="black" d="M346.296,-514.797C325.699,-522.857 299.069,-533.277 277.744,-541.622"/>
|
||||
<polygon fill="none" stroke="black" points="276.397,-538.391 268.36,-545.294 278.948,-544.909 276.397,-538.391"/>
|
||||
</g>
|
||||
<!-- \\MM_Page -->
|
||||
<g id="node28" class="node"><title>\\MM_Page</title>
|
||||
<a xlink:href="sys.page.html" xlink:title="MM_Page" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="411,-574 347,-574 347,-538 411,-538 411,-574"/>
|
||||
<text text-anchor="middle" x="379" y="-552.6" font-family="Courier,monospace" font-size="11.00">MM_Page</text>
|
||||
<a xlink:href="sys.core.page.html" xlink:title="MM_Page" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="411,-628 347,-628 347,-592 411,-592 411,-628"/>
|
||||
<text text-anchor="middle" x="379" y="-606.6" font-family="Courier,monospace" font-size="11.00">MM_Page</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\MM_Page->\\MM -->
|
||||
<g id="edge45" class="edge"><title>\\MM_Page->\\MM</title>
|
||||
<path fill="none" stroke="black" d="M346.296,-543.203C325.699,-535.143 299.069,-524.723 277.744,-516.378"/>
|
||||
<polygon fill="none" stroke="black" points="278.948,-513.091 268.36,-512.706 276.397,-519.609 278.948,-513.091"/>
|
||||
<path fill="none" stroke="black" d="M346.296,-597.203C325.699,-589.143 299.069,-578.723 277.744,-570.378"/>
|
||||
<polygon fill="none" stroke="black" points="278.948,-567.091 268.36,-566.706 276.397,-573.609 278.948,-567.091"/>
|
||||
</g>
|
||||
<!-- \\MM_Controller -->
|
||||
<g id="node29" class="node"><title>\\MM_Controller</title>
|
||||
<a xlink:href="sys.controller.html" xlink:title="MM_Controller" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="627,-412 523,-412 523,-376 627,-376 627,-412"/>
|
||||
<text text-anchor="middle" x="575" y="-390.6" font-family="Courier,monospace" font-size="11.00">MM_Controller</text>
|
||||
<a xlink:href="sys.core.controller.html" xlink:title="MM_Controller" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="627,-466 523,-466 523,-430 627,-430 627,-466"/>
|
||||
<text text-anchor="middle" x="575" y="-444.6" font-family="Courier,monospace" font-size="11.00">MM_Controller</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\MM_Controller->\\miniMVC -->
|
||||
<g id="edge47" class="edge"><title>\\MM_Controller->\\miniMVC</title>
|
||||
<path fill="none" stroke="black" d="M522.476,-408.471C490.93,-417.162 451.306,-428.079 421.696,-436.237"/>
|
||||
<polygon fill="none" stroke="black" points="420.381,-432.969 411.67,-438.999 422.24,-439.717 420.381,-432.969"/>
|
||||
<path fill="none" stroke="black" d="M522.476,-462.471C490.93,-471.162 451.306,-482.079 421.696,-490.237"/>
|
||||
<polygon fill="none" stroke="black" points="420.381,-486.969 411.67,-492.999 422.24,-493.717 420.381,-486.969"/>
|
||||
</g>
|
||||
<!-- \\MM_Output -->
|
||||
<g id="node30" class="node"><title>\\MM_Output</title>
|
||||
<a xlink:href="sys.output.html" xlink:title="MM_Output" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="418,-520 340,-520 340,-484 418,-484 418,-520"/>
|
||||
<text text-anchor="middle" x="379" y="-498.6" font-family="Courier,monospace" font-size="11.00">MM_Output</text>
|
||||
<a xlink:href="sys.core.output.html" xlink:title="MM_Output" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="418,-574 340,-574 340,-538 418,-538 418,-574"/>
|
||||
<text text-anchor="middle" x="379" y="-552.6" font-family="Courier,monospace" font-size="11.00">MM_Output</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\MM_Output->\\MM -->
|
||||
<g id="edge49" class="edge"><title>\\MM_Output->\\MM</title>
|
||||
<path fill="none" stroke="black" d="M339.824,-502C320.46,-502 297.217,-502 278.137,-502"/>
|
||||
<polygon fill="none" stroke="black" points="278.018,-498.5 268.018,-502 278.017,-505.5 278.018,-498.5"/>
|
||||
<path fill="none" stroke="black" d="M339.824,-556C320.46,-556 297.217,-556 278.137,-556"/>
|
||||
<polygon fill="none" stroke="black" points="278.018,-552.5 268.018,-556 278.017,-559.5 278.018,-552.5"/>
|
||||
</g>
|
||||
<!-- \\MM_Session -->
|
||||
<g id="node31" class="node"><title>\\MM_Session</title>
|
||||
<a xlink:href="sys.libraries.session.html" xlink:title="MM_Session" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="833,-196 749,-196 749,-160 833,-160 833,-196"/>
|
||||
<text text-anchor="middle" x="791" y="-174.6" font-family="Courier,monospace" font-size="11.00">MM_Session</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\Welcome_Model -->
|
||||
<g id="node31" class="node"><title>\\Welcome_Model</title>
|
||||
<g id="node32" class="node"><title>\\Welcome_Model</title>
|
||||
<a xlink:href="modules.welcome.models.welcome_model.html" xlink:title="Welcome_Model" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="843,-520 739,-520 739,-484 843,-484 843,-520"/>
|
||||
<text text-anchor="middle" x="791" y="-498.6" font-family="Courier,monospace" font-size="11.00">Welcome_Model</text>
|
||||
<polygon fill="none" stroke="black" points="843,-574 739,-574 739,-538 843,-538 843,-574"/>
|
||||
<text text-anchor="middle" x="791" y="-552.6" font-family="Courier,monospace" font-size="11.00">Welcome_Model</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\Welcome_Model->\\MM_Model -->
|
||||
<g id="edge51" class="edge"><title>\\Welcome_Model->\\MM_Model</title>
|
||||
<path fill="none" stroke="black" d="M738.988,-502C703.013,-502 655.582,-502 620.988,-502"/>
|
||||
<polygon fill="none" stroke="black" points="620.692,-498.5 610.692,-502 620.692,-505.5 620.692,-498.5"/>
|
||||
<path fill="none" stroke="black" d="M738.988,-556C703.013,-556 655.582,-556 620.988,-556"/>
|
||||
<polygon fill="none" stroke="black" points="620.692,-552.5 610.692,-556 620.692,-559.5 620.692,-552.5"/>
|
||||
</g>
|
||||
<!-- \\Welcome -->
|
||||
<g id="node32" class="node"><title>\\Welcome</title>
|
||||
<g id="node33" class="node"><title>\\Welcome</title>
|
||||
<a xlink:href="modules.welcome.controllers.welcome.html" xlink:title="Welcome" target="_parent">
|
||||
<polygon fill="none" stroke="black" points="823,-412 759,-412 759,-376 823,-376 823,-412"/>
|
||||
<text text-anchor="middle" x="791" y="-390.6" font-family="Courier,monospace" font-size="11.00">Welcome</text>
|
||||
<polygon fill="none" stroke="black" points="823,-466 759,-466 759,-430 823,-430 823,-466"/>
|
||||
<text text-anchor="middle" x="791" y="-444.6" font-family="Courier,monospace" font-size="11.00">Welcome</text>
|
||||
</a>
|
||||
</g>
|
||||
<!-- \\Welcome->\\MM_Controller -->
|
||||
<g id="edge53" class="edge"><title>\\Welcome->\\MM_Controller</title>
|
||||
<path fill="none" stroke="black" d="M758.663,-394C726.833,-394 677.382,-394 637.808,-394"/>
|
||||
<polygon fill="none" stroke="black" points="637.717,-390.5 627.716,-394 637.716,-397.5 637.717,-390.5"/>
|
||||
<path fill="none" stroke="black" d="M758.663,-448C726.833,-448 677.382,-448 637.808,-448"/>
|
||||
<polygon fill="none" stroke="black" points="637.717,-444.5 627.716,-448 637.716,-451.5 637.717,-444.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
@ -1583,7 +1583,7 @@ for complex select queries</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -679,7 +679,7 @@ the connection/database</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -152,7 +152,7 @@ and organizes database connections</p></p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -269,7 +269,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -209,7 +209,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -833,7 +833,7 @@ the last query executed</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -504,7 +504,7 @@ the query</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -297,7 +297,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -212,7 +212,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -434,7 +434,7 @@ dynamic methods</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -368,7 +368,7 @@
|
||||
</div>
|
||||
<a name="load_class" id="load_class"></a><div class="element clickable method public load_class" data-toggle="collapse" data-target=".load_class .collapse">
|
||||
<h2>Method to load classes into the singleton</h2>
|
||||
<pre>load_class(string $name, string $type) : void</pre>
|
||||
<pre>load_class(string $name) : void</pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
@ -381,10 +381,6 @@
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$type</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="load_config" id="load_config"></a><div class="element clickable method public load_config" data-toggle="collapse" data-target=".load_config .collapse">
|
||||
@ -764,7 +760,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -365,7 +365,7 @@
|
||||
</div>
|
||||
<a name="load_class" id="load_class"></a><div class="element clickable method public load_class" data-toggle="collapse" data-target=".load_class .collapse">
|
||||
<h2>Method to load classes into the singleton</h2>
|
||||
<pre>load_class(string $name, string $type) : void</pre>
|
||||
<pre>load_class(string $name) : void</pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
@ -378,10 +378,6 @@
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$type</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="load_config" id="load_config"></a><div class="element clickable method public load_config" data-toggle="collapse" data-target=".load_config .collapse">
|
||||
@ -728,7 +724,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -640,7 +640,7 @@ Used for outputing HTML</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -972,7 +972,7 @@ supports</p></p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
138
docs/classes/MM_Session.html
Normal file
138
docs/classes/MM_Session.html
Normal file
@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html><html xmlns:date="http://exslt.org/dates-and-times" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
||||
<meta charset="utf-8">
|
||||
<title>miniMVC » \MM_Session</title>
|
||||
<meta name="author" content="Mike van Riel">
|
||||
<meta name="description" content="">
|
||||
<link href="../css/template.css" rel="stylesheet" media="all">
|
||||
<script src="../js/jquery-1.7.1.min.js" type="text/javascript"></script><script src="../js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script><script src="../js/jquery.mousewheel.min.js" type="text/javascript"></script><script src="../js/bootstrap.js" type="text/javascript"></script><script src="../js/template.js" type="text/javascript"></script><script src="../js/prettify/prettify.min.js" type="text/javascript"></script><link rel="shortcut icon" href="../img/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="../img/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="../img/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="../img/apple-touch-icon-114x114.png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner"><div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></a><a class="brand" href="../index.html">miniMVC</a><div class="nav-collapse"><ul class="nav">
|
||||
<li class="dropdown">
|
||||
<a href="#api" class="dropdown-toggle" data-toggle="dropdown">
|
||||
API Documentation <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a>Packages</a></li>
|
||||
<li><a href="../packages/Default.html"><i class="icon-folder-open"></i> Default</a></li>
|
||||
<li><a href="../packages/Query.html"><i class="icon-folder-open"></i> Query</a></li>
|
||||
<li><a href="../packages/miniMVC.html"><i class="icon-folder-open"></i> miniMVC</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown" id="charts-menu">
|
||||
<a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Charts <b class="caret"></b></a><ul class="dropdown-menu"><li><a href="../graph_class.html"><i class="icon-list-alt"></i> Class hierarchy diagram</a></li></ul>
|
||||
</li>
|
||||
<li class="dropdown" id="reports-menu">
|
||||
<a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Reports <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a href="../errors.html"><i class="icon-remove-sign"></i> Errors
|
||||
<span class="label label-info">0</span></a></li>
|
||||
<li><a href="../markers.html"><i class="icon-map-marker"></i> Markers
|
||||
<ul></ul></a></li>
|
||||
<li><a href="../deprecated.html"><i class="icon-stop"></i> Deprecated elements
|
||||
<span class="label label-info">0</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul></div>
|
||||
</div></div>
|
||||
<div class="go_to_top"><a href="#___" style="color: inherit">Back to top <i class="icon-upload icon-white"></i></a></div>
|
||||
</div>
|
||||
<div id="___" class="container">
|
||||
<noscript><div class="alert alert-warning">
|
||||
Javascript is disabled; several features are only available
|
||||
if Javascript is enabled.
|
||||
</div></noscript>
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<span class="btn-group visibility" data-toggle="buttons-checkbox"><button class="btn public active" title="Show public elements">Public</button><button class="btn protected" title="Show protected elements">Protected</button><button class="btn private" title="Show private elements">Private</button><button class="btn inherited active" title="Show inherited elements">Inherited</button></span><div class="btn-group view pull-right" data-toggle="buttons-radio">
|
||||
<button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button><button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
|
||||
</div>
|
||||
<ul class="side-nav nav nav-list">
|
||||
<li class="nav-header">
|
||||
<i class="icon-custom icon-method"></i> Methods</li>
|
||||
<li class="method public "><a href="#__get" title="__get :: Retreive a session value"><span class="description">Retreive a session value</span><pre>__get()</pre></a></li>
|
||||
<li class="method public "><a href="#__set" title="__set :: Set a session value"><span class="description">Set a session value</span><pre>__set()</pre></a></li>
|
||||
<li class="method public "><a href="#destroy" title="destroy :: Destroy a session"><span class="description">Destroy a session</span><pre>destroy()</pre></a></li>
|
||||
<li class="nav-header protected">» Protected</li>
|
||||
<li class="method protected "><a href="#__construct" title="__construct :: Start a session"><span class="description">Start a session</span><pre>__construct()</pre></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span8">
|
||||
<a name="%5CMM_Session" id="\MM_Session"></a><div href="../classes/MM_Session.html" class="element class">
|
||||
<p class="short_description">Class to improve handling of PHP sessions</p>
|
||||
<div class="details">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>package</th>
|
||||
<td><a href="..//packages/miniMVC.Libraries.html">miniMVC</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>subpackage</th>
|
||||
<td>Libraries</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>
|
||||
<i class="icon-custom icon-method"></i> Methods</h3>
|
||||
<a name="__get" id="__get"></a><div class="element clickable method public __get" data-toggle="collapse" data-target=".__get .collapse">
|
||||
<h2>Retreive a session value</h2>
|
||||
<pre>__get(string $key) : mixed</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<h3>Parameters</h3>
|
||||
<div class="subelement argument">
|
||||
<h4>$key</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<h3>Returns</h3>
|
||||
<div class="subelement response"><code>mixed</code></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="__set" id="__set"></a><div class="element clickable method public __set" data-toggle="collapse" data-target=".__set .collapse">
|
||||
<h2>Set a session value</h2>
|
||||
<pre>__set(string $key, mixed $val) : void</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<h3>Parameters</h3>
|
||||
<div class="subelement argument">
|
||||
<h4>$key</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$val</h4>
|
||||
<code>mixed</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="destroy" id="destroy"></a><div class="element clickable method public destroy" data-toggle="collapse" data-target=".destroy .collapse">
|
||||
<h2>Destroy a session</h2>
|
||||
<pre>destroy() : void</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8"><p class="long_description"></p></div></div>
|
||||
</div>
|
||||
<a name="__construct" id="__construct"></a><div class="element clickable method protected __construct" data-toggle="collapse" data-target=".__construct .collapse">
|
||||
<h2>Start a session</h2>
|
||||
<pre>__construct() </pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8"><p class="long_description"></p></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -869,7 +869,7 @@ the connection/database</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -281,7 +281,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -208,7 +208,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -871,7 +871,7 @@ the connection/database</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -281,7 +281,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -203,7 +203,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
633
docs/classes/PHP_Session.html
Normal file
633
docs/classes/PHP_Session.html
Normal file
@ -0,0 +1,633 @@
|
||||
<!DOCTYPE html><html xmlns:date="http://exslt.org/dates-and-times" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
||||
<meta charset="utf-8">
|
||||
<title>miniMVC » \PHP_Session</title>
|
||||
<meta name="author" content="Mike van Riel">
|
||||
<meta name="description" content="">
|
||||
<link href="../css/template.css" rel="stylesheet" media="all">
|
||||
<script src="../js/jquery-1.7.1.min.js" type="text/javascript"></script><script src="../js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script><script src="../js/jquery.mousewheel.min.js" type="text/javascript"></script><script src="../js/bootstrap.js" type="text/javascript"></script><script src="../js/template.js" type="text/javascript"></script><script src="../js/prettify/prettify.min.js" type="text/javascript"></script><link rel="shortcut icon" href="../img/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="../img/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="../img/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="../img/apple-touch-icon-114x114.png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner"><div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></a><a class="brand" href="../index.html">miniMVC</a><div class="nav-collapse"><ul class="nav">
|
||||
<li class="dropdown">
|
||||
<a href="#api" class="dropdown-toggle" data-toggle="dropdown">
|
||||
API Documentation <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a>Packages</a></li>
|
||||
<li><a href="../packages/Default.html"><i class="icon-folder-open"></i> Default</a></li>
|
||||
<li><a href="../packages/Query.html"><i class="icon-folder-open"></i> Query</a></li>
|
||||
<li><a href="../packages/miniMVC.html"><i class="icon-folder-open"></i> miniMVC</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown" id="charts-menu">
|
||||
<a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Charts <b class="caret"></b></a><ul class="dropdown-menu"><li><a href="../graph_class.html"><i class="icon-list-alt"></i> Class hierarchy diagram</a></li></ul>
|
||||
</li>
|
||||
<li class="dropdown" id="reports-menu">
|
||||
<a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Reports <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a href="../errors.html"><i class="icon-remove-sign"></i> Errors
|
||||
<span class="label label-info">0</span></a></li>
|
||||
<li><a href="../markers.html"><i class="icon-map-marker"></i> Markers
|
||||
<ul></ul></a></li>
|
||||
<li><a href="../deprecated.html"><i class="icon-stop"></i> Deprecated elements
|
||||
<span class="label label-info">0</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul></div>
|
||||
</div></div>
|
||||
<div class="go_to_top"><a href="#___" style="color: inherit">Back to top <i class="icon-upload icon-white"></i></a></div>
|
||||
</div>
|
||||
<div id="___" class="container">
|
||||
<noscript><div class="alert alert-warning">
|
||||
Javascript is disabled; several features are only available
|
||||
if Javascript is enabled.
|
||||
</div></noscript>
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<span class="btn-group visibility" data-toggle="buttons-checkbox"><button class="btn public active" title="Show public elements">Public</button><button class="btn protected" title="Show protected elements">Protected</button><button class="btn private" title="Show private elements">Private</button><button class="btn inherited active" title="Show inherited elements">Inherited</button></span><div class="btn-group view pull-right" data-toggle="buttons-radio">
|
||||
<button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button><button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
|
||||
</div>
|
||||
<ul class="side-nav nav nav-list">
|
||||
<li class="nav-header">
|
||||
<i class="icon-custom icon-method"></i> Methods</li>
|
||||
<li class="method public inherited"><a href="#__call" title="__call :: Allow calling of array methods on the object and
|
||||
dynamic methods"><span class="description">Allow calling of array methods on the object and
|
||||
dynamic methods</span><pre>__call()</pre></a></li>
|
||||
<li class="method public "><a href="#__get" title="__get :: Retreive a session value"><span class="description">Retreive a session value</span><pre>__get()</pre></a></li>
|
||||
<li class="method public "><a href="#__set" title="__set :: Set a session value"><span class="description">Set a session value</span><pre>__set()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#append" title="append :: "><span class="description">append()
|
||||
</span><pre>append()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#asort" title="asort :: "><span class="description">asort()
|
||||
</span><pre>asort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#count" title="count :: "><span class="description">count()
|
||||
</span><pre>count()</pre></a></li>
|
||||
<li class="method public "><a href="#destroy" title="destroy :: Destroy a session"><span class="description">Destroy a session</span><pre>destroy()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#exchangeArray" title="exchangeArray :: "><span class="description">exchangeArray()
|
||||
</span><pre>exchangeArray()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#getArrayCopy" title="getArrayCopy :: "><span class="description">getArrayCopy()
|
||||
</span><pre>getArrayCopy()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#getFlags" title="getFlags :: "><span class="description">getFlags()
|
||||
</span><pre>getFlags()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#getIterator" title="getIterator :: "><span class="description">getIterator()
|
||||
</span><pre>getIterator()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#getIteratorClass" title="getIteratorClass :: "><span class="description">getIteratorClass()
|
||||
</span><pre>getIteratorClass()</pre></a></li>
|
||||
<li class="method public "><a href="#get_instance" title="get_instance :: Return or create singleton"><span class="description">Return or create singleton</span><pre>get_instance()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#ksort" title="ksort :: "><span class="description">ksort()
|
||||
</span><pre>ksort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#natcasesort" title="natcasesort :: "><span class="description">natcasesort()
|
||||
</span><pre>natcasesort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#natsort" title="natsort :: "><span class="description">natsort()
|
||||
</span><pre>natsort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#offsetExists" title="offsetExists :: "><span class="description">offsetExists()
|
||||
</span><pre>offsetExists()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#offsetGet" title="offsetGet :: "><span class="description">offsetGet()
|
||||
</span><pre>offsetGet()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#offsetSet" title="offsetSet :: "><span class="description">offsetSet()
|
||||
</span><pre>offsetSet()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#offsetUnset" title="offsetUnset :: "><span class="description">offsetUnset()
|
||||
</span><pre>offsetUnset()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#serialize" title="serialize :: "><span class="description">serialize()
|
||||
</span><pre>serialize()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#setFlags" title="setFlags :: "><span class="description">setFlags()
|
||||
</span><pre>setFlags()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#setIteratorClass" title="setIteratorClass :: "><span class="description">setIteratorClass()
|
||||
</span><pre>setIteratorClass()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#uasort" title="uasort :: "><span class="description">uasort()
|
||||
</span><pre>uasort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#uksort" title="uksort :: "><span class="description">uksort()
|
||||
</span><pre>uksort()</pre></a></li>
|
||||
<li class="method public inherited"><a href="#unserialize" title="unserialize :: "><span class="description">unserialize()
|
||||
</span><pre>unserialize()</pre></a></li>
|
||||
<li class="nav-header protected">» Protected</li>
|
||||
<li class="method protected "><a href="#__construct" title="__construct :: Start a session"><span class="description">Start a session</span><pre>__construct()</pre></a></li>
|
||||
<li class="nav-header">
|
||||
<i class="icon-custom icon-property"></i> Properties</li>
|
||||
<li class="nav-header protected">» Protected</li>
|
||||
<li class="property protected "><a href="#%24instance" title="$instance :: Instance of the current class"><span class="description">Instance of the current class</span><pre>$instance</pre></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span8">
|
||||
<a name="%5CPHP_Session" id="\PHP_Session"></a><div href="../classes/PHP_Session.html" class="element class">
|
||||
<p class="short_description">Class to improve handling of PHP sessions</p>
|
||||
<div class="details">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>package</th>
|
||||
<td><a href="..//packages/miniMVC.Libraries.html">miniMVC</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>subpackage</th>
|
||||
<td>Libraries</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>
|
||||
<i class="icon-custom icon-method"></i> Methods</h3>
|
||||
<a name="__call" id="__call"></a><div class="element clickable method public __call" data-toggle="collapse" data-target=".__call .collapse">
|
||||
<h2>Allow calling of array methods on the object and
|
||||
dynamic methods</h2>
|
||||
<pre>__call(string $name, array $params) : mixed</pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered"><tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::__call()</td>
|
||||
</tr></table>
|
||||
<h3>Parameters</h3>
|
||||
<div class="subelement argument">
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$params</h4>
|
||||
<code>array</code>
|
||||
</div>
|
||||
<h3>Returns</h3>
|
||||
<div class="subelement response"><code>mixed</code></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="__get" id="__get"></a><div class="element clickable method public __get" data-toggle="collapse" data-target=".__get .collapse">
|
||||
<h2>Retreive a session value</h2>
|
||||
<pre>__get(string $key) : mixed</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<h3>Parameters</h3>
|
||||
<div class="subelement argument">
|
||||
<h4>$key</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<h3>Returns</h3>
|
||||
<div class="subelement response"><code>mixed</code></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="__set" id="__set"></a><div class="element clickable method public __set" data-toggle="collapse" data-target=".__set .collapse">
|
||||
<h2>Set a session value</h2>
|
||||
<pre>__set(string $key, mixed $val) : void</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<h3>Parameters</h3>
|
||||
<div class="subelement argument">
|
||||
<h4>$key</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$val</h4>
|
||||
<code>mixed</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="append" id="append"></a><div class="element clickable method public append" data-toggle="collapse" data-target=".append .collapse">
|
||||
<h2>append()
|
||||
</h2>
|
||||
<pre>append() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::append()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::append()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="asort" id="asort"></a><div class="element clickable method public asort" data-toggle="collapse" data-target=".asort .collapse">
|
||||
<h2>asort()
|
||||
</h2>
|
||||
<pre>asort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::asort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::asort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="count" id="count"></a><div class="element clickable method public count" data-toggle="collapse" data-target=".count .collapse">
|
||||
<h2>count()
|
||||
</h2>
|
||||
<pre>count() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::count()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::count()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="destroy" id="destroy"></a><div class="element clickable method public destroy" data-toggle="collapse" data-target=".destroy .collapse">
|
||||
<h2>Destroy a session</h2>
|
||||
<pre>destroy() : void</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8"><p class="long_description"></p></div></div>
|
||||
</div>
|
||||
<a name="exchangeArray" id="exchangeArray"></a><div class="element clickable method public exchangeArray" data-toggle="collapse" data-target=".exchangeArray .collapse">
|
||||
<h2>exchangeArray()
|
||||
</h2>
|
||||
<pre>exchangeArray() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::exchangeArray()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::exchangeArray()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="getArrayCopy" id="getArrayCopy"></a><div class="element clickable method public getArrayCopy" data-toggle="collapse" data-target=".getArrayCopy .collapse">
|
||||
<h2>getArrayCopy()
|
||||
</h2>
|
||||
<pre>getArrayCopy() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::getArrayCopy()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::getArrayCopy()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="getFlags" id="getFlags"></a><div class="element clickable method public getFlags" data-toggle="collapse" data-target=".getFlags .collapse">
|
||||
<h2>getFlags()
|
||||
</h2>
|
||||
<pre>getFlags() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::getFlags()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::getFlags()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="getIterator" id="getIterator"></a><div class="element clickable method public getIterator" data-toggle="collapse" data-target=".getIterator .collapse">
|
||||
<h2>getIterator()
|
||||
</h2>
|
||||
<pre>getIterator() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::getIterator()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::getIterator()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="getIteratorClass" id="getIteratorClass"></a><div class="element clickable method public getIteratorClass" data-toggle="collapse" data-target=".getIteratorClass .collapse">
|
||||
<h2>getIteratorClass()
|
||||
</h2>
|
||||
<pre>getIteratorClass() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::getIteratorClass()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::getIteratorClass()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="get_instance" id="get_instance"></a><div class="element clickable method public get_instance" data-toggle="collapse" data-target=".get_instance .collapse">
|
||||
<h2>Return or create singleton</h2>
|
||||
<pre>get_instance() : <a href="../classes/PHP_Session.html">\PHP_Session</a></pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered"><tr>
|
||||
<th>fluent</th>
|
||||
<td>This method is part of a fluent interface and will return the same instance</td>
|
||||
</tr></table>
|
||||
<h3>Returns</h3>
|
||||
<div class="subelement response"><code><a href="../classes/PHP_Session.html">\PHP_Session</a></code></div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="ksort" id="ksort"></a><div class="element clickable method public ksort" data-toggle="collapse" data-target=".ksort .collapse">
|
||||
<h2>ksort()
|
||||
</h2>
|
||||
<pre>ksort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::ksort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::ksort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="natcasesort" id="natcasesort"></a><div class="element clickable method public natcasesort" data-toggle="collapse" data-target=".natcasesort .collapse">
|
||||
<h2>natcasesort()
|
||||
</h2>
|
||||
<pre>natcasesort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::natcasesort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::natcasesort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="natsort" id="natsort"></a><div class="element clickable method public natsort" data-toggle="collapse" data-target=".natsort .collapse">
|
||||
<h2>natsort()
|
||||
</h2>
|
||||
<pre>natsort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::natsort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::natsort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="offsetExists" id="offsetExists"></a><div class="element clickable method public offsetExists" data-toggle="collapse" data-target=".offsetExists .collapse">
|
||||
<h2>offsetExists()
|
||||
</h2>
|
||||
<pre>offsetExists() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::offsetExists()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::offsetExists()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="offsetGet" id="offsetGet"></a><div class="element clickable method public offsetGet" data-toggle="collapse" data-target=".offsetGet .collapse">
|
||||
<h2>offsetGet()
|
||||
</h2>
|
||||
<pre>offsetGet() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::offsetGet()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::offsetGet()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="offsetSet" id="offsetSet"></a><div class="element clickable method public offsetSet" data-toggle="collapse" data-target=".offsetSet .collapse">
|
||||
<h2>offsetSet()
|
||||
</h2>
|
||||
<pre>offsetSet() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::offsetSet()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::offsetSet()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="offsetUnset" id="offsetUnset"></a><div class="element clickable method public offsetUnset" data-toggle="collapse" data-target=".offsetUnset .collapse">
|
||||
<h2>offsetUnset()
|
||||
</h2>
|
||||
<pre>offsetUnset() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::offsetUnset()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::offsetUnset()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="serialize" id="serialize"></a><div class="element clickable method public serialize" data-toggle="collapse" data-target=".serialize .collapse">
|
||||
<h2>serialize()
|
||||
</h2>
|
||||
<pre>serialize() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::serialize()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::serialize()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="setFlags" id="setFlags"></a><div class="element clickable method public setFlags" data-toggle="collapse" data-target=".setFlags .collapse">
|
||||
<h2>setFlags()
|
||||
</h2>
|
||||
<pre>setFlags() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::setFlags()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::setFlags()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="setIteratorClass" id="setIteratorClass"></a><div class="element clickable method public setIteratorClass" data-toggle="collapse" data-target=".setIteratorClass .collapse">
|
||||
<h2>setIteratorClass()
|
||||
</h2>
|
||||
<pre>setIteratorClass() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::setIteratorClass()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::setIteratorClass()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="uasort" id="uasort"></a><div class="element clickable method public uasort" data-toggle="collapse" data-target=".uasort .collapse">
|
||||
<h2>uasort()
|
||||
</h2>
|
||||
<pre>uasort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::uasort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::uasort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="uksort" id="uksort"></a><div class="element clickable method public uksort" data-toggle="collapse" data-target=".uksort .collapse">
|
||||
<h2>uksort()
|
||||
</h2>
|
||||
<pre>uksort() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::uksort()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::uksort()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="unserialize" id="unserialize"></a><div class="element clickable method public unserialize" data-toggle="collapse" data-target=".unserialize .collapse">
|
||||
<h2>unserialize()
|
||||
</h2>
|
||||
<pre>unserialize() </pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>ArrayObject::unserialize()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>inherited_from</th>
|
||||
<td>\MM::unserialize()</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="__construct" id="__construct"></a><div class="element clickable method protected __construct" data-toggle="collapse" data-target=".__construct .collapse">
|
||||
<h2>Start a session</h2>
|
||||
<pre>__construct() </pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8"><p class="long_description"></p></div></div>
|
||||
</div>
|
||||
<h3>
|
||||
<i class="icon-custom icon-property"></i> Properties</h3>
|
||||
<a name="%24instance" id="$instance"> </a><div class="element clickable property protected $instance" data-toggle="collapse" data-target=".$instance .collapse">
|
||||
<h2>Instance of the current class</h2>
|
||||
<pre>$instance : <a href="../classes/PHP_Session.html">\PHP_Session</a></pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8"><p class="long_description"></p></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T12:48:51-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -871,7 +871,7 @@ the connection/database</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -297,7 +297,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -208,7 +208,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1222,7 +1222,7 @@ for complex select queries</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -886,7 +886,7 @@ method if the database does not support 'TRUNCATE';</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -281,7 +281,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -208,7 +208,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -244,7 +244,7 @@ directly - the settings should be safe!</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -418,7 +418,7 @@
|
||||
</div>
|
||||
<a name="load_class" id="load_class"></a><div class="element clickable method public load_class" data-toggle="collapse" data-target=".load_class .collapse">
|
||||
<h2>Method to load classes into the singleton</h2>
|
||||
<pre>load_class(string $name, string $type) : void</pre>
|
||||
<pre>load_class(string $name) : void</pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
@ -437,10 +437,6 @@
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$type</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="load_config" id="load_config"></a><div class="element clickable method public load_config" data-toggle="collapse" data-target=".load_config .collapse">
|
||||
@ -906,7 +902,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -407,7 +407,7 @@
|
||||
</div>
|
||||
<a name="load_class" id="load_class"></a><div class="element clickable method public load_class" data-toggle="collapse" data-target=".load_class .collapse">
|
||||
<h2>Method to load classes into the singleton</h2>
|
||||
<pre>load_class(string $name, string $type) : void</pre>
|
||||
<pre>load_class(string $name) : void</pre>
|
||||
<div class="labels"><span class="label">Inherited</span></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
@ -426,10 +426,6 @@
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$type</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="load_config" id="load_config"></a><div class="element clickable method public load_config" data-toggle="collapse" data-target=".load_config .collapse">
|
||||
@ -846,7 +842,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -331,7 +331,7 @@
|
||||
</div>
|
||||
<a name="load_class" id="load_class"></a><div class="element clickable method public load_class" data-toggle="collapse" data-target=".load_class .collapse">
|
||||
<h2>Method to load classes into the singleton</h2>
|
||||
<pre>load_class(string $name, string $type) : void</pre>
|
||||
<pre>load_class(string $name) : void</pre>
|
||||
<div class="labels"></div>
|
||||
<div class="row collapse"><div class="span8">
|
||||
<p class="long_description"></p>
|
||||
@ -340,10 +340,6 @@
|
||||
<h4>$name</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
<div class="subelement argument">
|
||||
<h4>$type</h4>
|
||||
<code>string</code>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
<a name="load_config" id="load_config"></a><div class="element clickable method public load_config" data-toggle="collapse" data-target=".load_config .collapse">
|
||||
@ -615,7 +611,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -67,7 +67,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -101,12 +101,13 @@
|
||||
<div class="package-contents"></div>
|
||||
<div class="package-contents"></div>
|
||||
<div class="package-contents"></div>
|
||||
<div class="package-contents"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -64,7 +64,7 @@
|
||||
</script><div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -80,7 +80,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -69,7 +69,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -448,6 +448,13 @@ data-fetching methods</p>
|
||||
<div class="details collapse"></div>
|
||||
<a href="../classes/MM_Page.html" class="more">« More »</a>
|
||||
</div>
|
||||
<a name="MM_Session" id="MM_Session"></a><div class="element ajax clickable class" href="../classes/MM_Session.html">
|
||||
<h1>MM_Session<a href="../classes/MM_Session.html">¶</a>
|
||||
</h1>
|
||||
<p class="short_description">Class to improve handling of PHP sessions</p>
|
||||
<div class="details collapse"></div>
|
||||
<a href="../classes/MM_Session.html" class="more">« More »</a>
|
||||
</div>
|
||||
<a name="MySQL" id="MySQL"></a><div class="element ajax clickable class" href="../classes/MySQL.html">
|
||||
<h1>MySQL<a href="../classes/MySQL.html">¶</a>
|
||||
</h1>
|
||||
@ -702,7 +709,7 @@ instantiates the specific db driver</p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -67,7 +67,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -185,7 +185,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -211,7 +211,7 @@ data-fetching methods</p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -97,7 +97,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -115,7 +115,7 @@ instantiates the specific db driver</p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -316,7 +316,7 @@ instantiates the specific db driver</p>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -139,7 +139,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
95
docs/packages/miniMVC.Libraries.html
Normal file
95
docs/packages/miniMVC.Libraries.html
Normal file
@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html><html xmlns:date="http://exslt.org/dates-and-times" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
||||
<meta charset="utf-8">
|
||||
<title>miniMVC » miniMVC\Libraries</title>
|
||||
<meta name="author" content="Mike van Riel">
|
||||
<meta name="description" content="">
|
||||
<link href="../css/template.css" rel="stylesheet" media="all">
|
||||
<script src="../js/jquery-1.7.1.min.js" type="text/javascript"></script><script src="../js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script><script src="../js/jquery.mousewheel.min.js" type="text/javascript"></script><script src="../js/bootstrap.js" type="text/javascript"></script><script src="../js/template.js" type="text/javascript"></script><script src="../js/prettify/prettify.min.js" type="text/javascript"></script><link rel="shortcut icon" href="../img/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="../img/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="../img/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="../img/apple-touch-icon-114x114.png">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner"><div class="container">
|
||||
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></a><a class="brand" href="../index.html">miniMVC</a><div class="nav-collapse"><ul class="nav">
|
||||
<li class="dropdown">
|
||||
<a href="#api" class="dropdown-toggle" data-toggle="dropdown">
|
||||
API Documentation <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a>Packages</a></li>
|
||||
<li><a href="../packages/Default.html"><i class="icon-folder-open"></i> Default</a></li>
|
||||
<li><a href="../packages/Query.html"><i class="icon-folder-open"></i> Query</a></li>
|
||||
<li><a href="../packages/miniMVC.html"><i class="icon-folder-open"></i> miniMVC</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown" id="charts-menu">
|
||||
<a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Charts <b class="caret"></b></a><ul class="dropdown-menu"><li><a href="../graph_class.html"><i class="icon-list-alt"></i> Class hierarchy diagram</a></li></ul>
|
||||
</li>
|
||||
<li class="dropdown" id="reports-menu">
|
||||
<a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
|
||||
Reports <b class="caret"></b></a><ul class="dropdown-menu">
|
||||
<li><a href="../errors.html"><i class="icon-remove-sign"></i> Errors
|
||||
<span class="label label-info">0</span></a></li>
|
||||
<li><a href="../markers.html"><i class="icon-map-marker"></i> Markers
|
||||
<ul></ul></a></li>
|
||||
<li><a href="../deprecated.html"><i class="icon-stop"></i> Deprecated elements
|
||||
<span class="label label-info">0</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul></div>
|
||||
</div></div>
|
||||
<div class="go_to_top"><a href="#___" style="color: inherit">Back to top <i class="icon-upload icon-white"></i></a></div>
|
||||
</div>
|
||||
<div id="___" class="container">
|
||||
<noscript><div class="alert alert-warning">
|
||||
Javascript is disabled; several features are only available
|
||||
if Javascript is enabled.
|
||||
</div></noscript>
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<div class="btn-group view pull-right" data-toggle="buttons-radio">
|
||||
<button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button><button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
|
||||
</div>
|
||||
<ul class="side-nav nav nav-list">
|
||||
<li class="nav-header">
|
||||
<i class="icon-map-marker"></i> Packages</li>
|
||||
<li>
|
||||
<a href="../packages/miniMVC.Libraries.html" title="Libraries"><i class="icon-folder-open"></i>Libraries</a><ul class="nav nav-list nav-packages"></ul>
|
||||
</li>
|
||||
<li class="nav-header">
|
||||
<i class="icon-custom icon-class"></i> Classes</li>
|
||||
<li><a href="#MM_Session" title="Class to improve handling of PHP sessions">MM_Session</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span8 package-contents">
|
||||
<ul class="breadcrumb">
|
||||
<li>
|
||||
<a href="../index.html"><i class="icon-folder-open"></i></a><span class="divider">\</span>
|
||||
</li>
|
||||
<li><a href="../packages/miniMVC.html">miniMVC</a></li>
|
||||
<span class="divider">\</span><li class="active"><a href="../packages/miniMVC.Libraries.html">Libraries</a></li>
|
||||
</ul>
|
||||
<div class="package-indent">
|
||||
<h3>
|
||||
<i class="icon-custom icon-class"></i> Classes and interfaces</h3>
|
||||
<a name="MM_Session" id="MM_Session"></a><div class="element ajax clickable class" href="../classes/MM_Session.html">
|
||||
<h1>MM_Session<a href="../classes/MM_Session.html">¶</a>
|
||||
</h1>
|
||||
<p class="short_description">Class to improve handling of PHP sessions</p>
|
||||
<div class="details collapse"></div>
|
||||
<a href="../classes/MM_Session.html" class="more">« More »</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -137,7 +137,7 @@
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -63,6 +63,9 @@
|
||||
<a href="../packages/miniMVC.App.html" title="App"><i class="icon-folder-open"></i>App</a><ul class="nav nav-list nav-packages"></ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="../packages/miniMVC.Libraries.html" title="Libraries"><i class="icon-folder-open"></i>Libraries</a><ul class="nav nav-list nav-packages"></ul>
|
||||
</li>
|
||||
<li>
|
||||
<a href="../packages/miniMVC.System.html" title="System"><i class="icon-folder-open"></i>System</a><ul class="nav nav-list nav-packages"></ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -413,6 +416,24 @@ display them cleanly</h2>
|
||||
<a href="../index.html"><i class="icon-folder-open"></i></a><span class="divider">\</span>
|
||||
</li>
|
||||
<li><a href="../packages/miniMVC.html">miniMVC</a></li>
|
||||
<span class="divider">\</span><li class="active"><a href="../packages/miniMVC.Libraries.html">Libraries</a></li>
|
||||
</ul>
|
||||
<div class="package-indent">
|
||||
<h3>
|
||||
<i class="icon-custom icon-class"></i> Classes and interfaces</h3>
|
||||
<a name="MM_Session" id="MM_Session"></a><div class="element ajax clickable class" href="../classes/MM_Session.html">
|
||||
<h1>MM_Session<a href="../classes/MM_Session.html">¶</a>
|
||||
</h1>
|
||||
<p class="short_description">Class to improve handling of PHP sessions</p>
|
||||
<div class="details collapse"></div>
|
||||
<a href="../classes/MM_Session.html" class="more">« More »</a>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="breadcrumb">
|
||||
<li>
|
||||
<a href="../index.html"><i class="icon-folder-open"></i></a><span class="divider">\</span>
|
||||
</li>
|
||||
<li><a href="../packages/miniMVC.html">miniMVC</a></li>
|
||||
<span class="divider">\</span><li class="active"><a href="../packages/miniMVC.System.html">System</a></li>
|
||||
</ul>
|
||||
<div class="package-indent">
|
||||
@ -474,7 +495,7 @@ display them cleanly</h2>
|
||||
<div class="row"><footer class="span12">
|
||||
Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br>
|
||||
Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor 2.0.0a2</a> and<br>
|
||||
generated on 2012-05-03T11:38:41-04:00.<br></footer></div>
|
||||
generated on 2012-05-03T13:23:53-04:00.<br></footer></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -95,7 +95,7 @@ and organizes database connections</p>]]></long-description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/classes/settings.php" hash="69d30a582c8ec7f2a29151aab896ce1e" package="Query">
|
||||
<file path="sys/db/classes/settings.php" hash="25ad9e3275da6ce2f7330da60951bc89" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -510,7 +510,7 @@ directly - the settings should be safe!]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/classes/db_pdo.php" hash="343830257e8bc84fe3ef14bafbec5287" package="Query">
|
||||
<file path="sys/db/classes/db_pdo.php" hash="4a064284a9d84b52efed79aea6180eeb" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -2494,7 +2494,7 @@ in place of the get() method]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/autoload.php" hash="170d8d1f4b74767beb653875962976ae" package="Query">
|
||||
<file path="sys/db/autoload.php" hash="bdce746964645c481b110b7742a1691b" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -2568,7 +2568,7 @@ with array_map and glob]]></description>
|
||||
</argument>
|
||||
</function>
|
||||
</file>
|
||||
<file path="sys/db/drivers/pgsql/pgsql_sql.php" hash="28f1fe85be6eba57e8ec7373f885faec" package="Default">
|
||||
<file path="sys/db/drivers/pgsql/pgsql_sql.php" hash="bacf01d4b1126f518af6577005ee7ef3" package="Default">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -2742,7 +2742,7 @@ with array_map and glob]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/drivers/pgsql/pgsql_util.php" hash="5bc6c47b681f4bdbb9385d8101666760" package="Query">
|
||||
<file path="sys/db/drivers/pgsql/pgsql_util.php" hash="a649c231c8c931df95afecfe9df3dba4" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -3369,7 +3369,7 @@ with array_map and glob]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/drivers/mysql/mysql_util.php" hash="e6dbdd9b0b965f7e09ee0638ed4a7a35" package="Query">
|
||||
<file path="sys/db/drivers/mysql/mysql_util.php" hash="ab0732f6bec207873af7a07ff1a0e1e8" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -3763,7 +3763,7 @@ with array_map and glob]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/drivers/sqlite/sqlite_util.php" hash="18cd637365896dd9cf94066e517cdaa8" package="Query">
|
||||
<file path="sys/db/drivers/sqlite/sqlite_util.php" hash="5d6c375946512b2b5a5b39bd4ce55ac9" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -4762,7 +4762,7 @@ the query]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/drivers/firebird/firebird_driver.php" hash="4f7e9df014cc1df6b92f09f815b9837d" package="Query">
|
||||
<file path="sys/db/drivers/firebird/firebird_driver.php" hash="6210fab7af8f0e2b5b95e048d2f80beb" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -5078,7 +5078,7 @@ the last query executed]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/db/drivers/firebird/firebird_util.php" hash="e51cf49b7bb1e2bb39ed5eab9bf6e98c" package="Query">
|
||||
<file path="sys/db/drivers/firebird/firebird_util.php" hash="6c6a6d2b3f952ce5bf66c31ade5d346c" package="Query">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[Query]]></description>
|
||||
<long-description><![CDATA[<p>Free Query Builder / Database Abstraction Layer</p>]]></long-description>
|
||||
@ -5219,7 +5219,7 @@ the last query executed]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/model.php" hash="01891d05727784017f7df2ba5c599ba3" package="miniMVC">
|
||||
<file path="sys/core/model.php" hash="01891d05727784017f7df2ba5c599ba3" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -5271,275 +5271,7 @@ the last query executed]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/common.php" hash="60f0a7d073a110e7b52eaf325800a131" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
<tag line="2" name="package" description="miniMVC"/>
|
||||
<tag line="2" name="author" description="Timothy J. Warren"/>
|
||||
<tag line="2" name="copyright" description="Copyright (c) 2011 - 2012"/>
|
||||
<tag line="2" name="link" description="https://github.com/timw4mail/miniMVC" link="https://github.com/timw4mail/miniMVC"/>
|
||||
<tag line="2" name="license" description="http://philsturgeon.co.uk/code/dbad-license"/>
|
||||
</docblock>
|
||||
<include line="396" type="Require Once" package="Default">
|
||||
<name>db/autoload.php</name>
|
||||
</include>
|
||||
<include line="399" type="Require Once" package="Default">
|
||||
<name>miniMVC.php</name>
|
||||
</include>
|
||||
<function namespace="default" line="32" package="miniMVC">
|
||||
<name>shutdown</name>
|
||||
<type>function</type>
|
||||
<docblock line="25">
|
||||
<description><![CDATA[Function to run on script shutdown
|
||||
-used to catch most fatal errors, and
|
||||
display them cleanly]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="25" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="64" package="miniMVC">
|
||||
<name>load_file</name>
|
||||
<type>function</type>
|
||||
<docblock line="57">
|
||||
<description><![CDATA[Function to search through the tree to find the necessary file]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="57" name="param" description="" type="string" variable="$file">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="57" name="param" description="" type="string" variable="$curr_path">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="57" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="64">
|
||||
<name>$file</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="64">
|
||||
<name>$curr_path</name>
|
||||
<default><![CDATA[""]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="99" package="miniMVC">
|
||||
<name>on_error</name>
|
||||
<type>function</type>
|
||||
<docblock line="90">
|
||||
<description><![CDATA[Custom error handler]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="90" name="param" description="" type="int" variable="$severity">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="string" variable="$message">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="string" variable="$filepath">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="int" variable="$line">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
<tag line="90" name="return" description="" type="\ErrorException">
|
||||
<type by_reference="false">\ErrorException</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="99">
|
||||
<name>$severity</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$message</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$filepath</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$line</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="112" package="miniMVC">
|
||||
<name>on_exception</name>
|
||||
<type>function</type>
|
||||
<docblock line="106">
|
||||
<description><![CDATA[Custom exception handlererror_get_last]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="106" name="param" description="" type="\Exception" variable="$exception">
|
||||
<type by_reference="false">\Exception</type>
|
||||
</tag>
|
||||
<tag line="106" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="112">
|
||||
<name>$exception</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="134" package="miniMVC">
|
||||
<name>is_like_array</name>
|
||||
<type>function</type>
|
||||
<docblock line="128">
|
||||
<description><![CDATA[Utility function to check if a variable is set, and is an array or object]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="128" name="param" description="" type="mixed" variable="$var">
|
||||
<type by_reference="false">mixed</type>
|
||||
</tag>
|
||||
<tag line="128" name="return" description="" type="bool">
|
||||
<type by_reference="false">bool</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="134">
|
||||
<name>$var</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="151" package="miniMVC">
|
||||
<name>show_404</name>
|
||||
<type>function</type>
|
||||
<docblock line="146">
|
||||
<description><![CDATA[General 404 function]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="146" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="175" package="miniMVC">
|
||||
<name>show_error</name>
|
||||
<type>function</type>
|
||||
<docblock line="169">
|
||||
<description><![CDATA[Fatal Error page function]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="169" name="param" description="" type="string" variable="$message">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="169" name="param" description="" type="int" variable="$status_code">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="175">
|
||||
<name>$message</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="175">
|
||||
<name>$status_code</name>
|
||||
<default><![CDATA[null]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="200" package="miniMVC">
|
||||
<name>controller_methods</name>
|
||||
<type>function</type>
|
||||
<docblock line="194">
|
||||
<description><![CDATA[Returns routable methods for the specified controller class]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="194" name="param" description="" type="string" variable="$controller">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="194" name="return" description="" type="array">
|
||||
<type by_reference="false">array</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="200">
|
||||
<name>$controller</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="218" package="miniMVC">
|
||||
<name>route</name>
|
||||
<type>function</type>
|
||||
<docblock line="213">
|
||||
<description><![CDATA[Calls the appropriate module/controller/function based on the url]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="213" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="342" package="miniMVC">
|
||||
<name>site_url</name>
|
||||
<type>function</type>
|
||||
<docblock line="336">
|
||||
<description><![CDATA[Returns a full url from a url segment]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="336" name="param" description="" type="string" variable="$segment">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="336" name="return" description="" type="string">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="342">
|
||||
<name>$segment</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="356" package="miniMVC">
|
||||
<name>to_string</name>
|
||||
<type>function</type>
|
||||
<docblock line="349">
|
||||
<description><![CDATA[Prints out the contents of the object]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="349" name="param" description="" type="\object/array" variable="$data">
|
||||
<type by_reference="false">\object/array</type>
|
||||
</tag>
|
||||
<tag line="349" name="param" description="" type="string" variable="$method">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="349" name="return" description="" type="string">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="356">
|
||||
<name>$data</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="356">
|
||||
<name>$method</name>
|
||||
<default><![CDATA['print_r']]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="390" package="miniMVC">
|
||||
<name>do_include</name>
|
||||
<type>function</type>
|
||||
<docblock line="384">
|
||||
<description><![CDATA[Array_map callback to load a folder of classes at once]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="384" name="param" description="" type="string" variable="$path">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="384" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="390">
|
||||
<name>$path</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
</file>
|
||||
<file path="sys/db.php" hash="fb3bc02ed59a592ed41e961727a63c2a" package="miniMVC">
|
||||
<file path="sys/core/db.php" hash="2dd4b1ad5928f6f27318c77b6f4a130e" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -5653,7 +5385,7 @@ display them cleanly]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/miniMVC.php" hash="beab708bbf1a7169e150bd1948d26ce7" package="miniMVC">
|
||||
<file path="sys/core/miniMVC.php" hash="c2a34e78f2511d0be859165251595469" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -5869,7 +5601,7 @@ dynamic methods]]></description>
|
||||
<type/>
|
||||
</argument>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="314" package="">
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="313" package="">
|
||||
<name>load_class</name>
|
||||
<type>function</type>
|
||||
<docblock line="307">
|
||||
@ -5878,51 +5610,43 @@ dynamic methods]]></description>
|
||||
<tag line="307" name="param" description="" type="string" variable="$name">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="307" name="param" description="" type="string" variable="$type">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="307" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="314">
|
||||
<argument line="313">
|
||||
<name>$name</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="314">
|
||||
<name>$type</name>
|
||||
<default><![CDATA['class']]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="370" package="">
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="371" package="">
|
||||
<name>unload</name>
|
||||
<type>function</type>
|
||||
<docblock line="365">
|
||||
<docblock line="366">
|
||||
<description><![CDATA[Convenience function to remove an object from the singleton]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="365" name="param" description="" type="string" variable="$name">
|
||||
<tag line="366" name="param" description="" type="string" variable="$name">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="370">
|
||||
<argument line="371">
|
||||
<name>$name</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="385" package="">
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="386" package="">
|
||||
<name>load_config</name>
|
||||
<type>function</type>
|
||||
<docblock line="380">
|
||||
<docblock line="381">
|
||||
<description><![CDATA[Convenience function to load config files]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="380" name="param" description="" type="string" variable="$name">
|
||||
<tag line="381" name="param" description="" type="string" variable="$name">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="385">
|
||||
<argument line="386">
|
||||
<name>$name</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
@ -5930,7 +5654,7 @@ dynamic methods]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/page.php" hash="ad9390e0d82e607ba67a4705a2ab8624" package="miniMVC">
|
||||
<file path="sys/core/page.php" hash="fe5e54476f922c47baf2ab9040a55f5b" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -6497,7 +6221,7 @@ page.</p>]]></long-description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/controller.php" hash="765cd2295836720906bdc3a4e3453626" package="miniMVC">
|
||||
<file path="sys/core/controller.php" hash="eac8dd511fb6b91e187a4749fd619b17" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -6603,7 +6327,7 @@ page.</p>]]></long-description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/output.php" hash="bbcd277d43771103de6f189f99c2a061" package="Default">
|
||||
<file path="sys/core/output.php" hash="b95af3c4fb386e999b088366cce23044" package="Default">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -6733,7 +6457,362 @@ Used for outputing HTML]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="index.php" hash="c31554a930dad7ae4ffda69df87ed227" package="miniMVC">
|
||||
<file path="sys/libraries/session.php" hash="08c3faccd0c710c5cf5acc1d3fc3ba23" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
<tag line="2" name="package" description="miniMVC"/>
|
||||
<tag line="2" name="author" description="Timothy J. Warren"/>
|
||||
<tag line="2" name="copyright" description="Copyright (c) 2011 - 2012"/>
|
||||
<tag line="2" name="link" description="https://github.com/timw4mail/miniMVC" link="https://github.com/timw4mail/miniMVC"/>
|
||||
<tag line="2" name="license" description="http://philsturgeon.co.uk/code/dbad-license"/>
|
||||
</docblock>
|
||||
<class final="false" abstract="false" namespace="default" line="22" package="miniMVC\Libraries">
|
||||
<name>MM_Session</name>
|
||||
<full_name>\MM_Session</full_name>
|
||||
<extends/>
|
||||
<docblock line="16">
|
||||
<description><![CDATA[Class to improve handling of PHP sessions]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="16" name="package" description="miniMVC"/>
|
||||
<tag line="16" name="subpackage" description="Libraries"/>
|
||||
</docblock>
|
||||
<method final="false" abstract="false" static="false" visibility="protected" namespace="default" line="32" package="">
|
||||
<name>__construct</name>
|
||||
<type>function</type>
|
||||
<docblock line="29">
|
||||
<description><![CDATA[Start a session]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
</docblock>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="53" package="">
|
||||
<name>__set</name>
|
||||
<type>function</type>
|
||||
<docblock line="46">
|
||||
<description><![CDATA[Set a session value]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="46" name="param" description="" type="string" variable="$key">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="46" name="param" description="" type="mixed" variable="$val">
|
||||
<type by_reference="false">mixed</type>
|
||||
</tag>
|
||||
<tag line="46" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="53">
|
||||
<name>$key</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="53">
|
||||
<name>$val</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="66" package="">
|
||||
<name>__get</name>
|
||||
<type>function</type>
|
||||
<docblock line="60">
|
||||
<description><![CDATA[Retreive a session value]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="60" name="param" description="" type="string" variable="$key">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="60" name="return" description="" type="mixed">
|
||||
<type by_reference="false">mixed</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="66">
|
||||
<name>$key</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="78" package="">
|
||||
<name>destroy</name>
|
||||
<type>function</type>
|
||||
<docblock line="73">
|
||||
<description><![CDATA[Destroy a session]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="73" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="sys/common.php" hash="c4342203d1f8cc49ff444580ee71dfdf" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
<tag line="2" name="package" description="miniMVC"/>
|
||||
<tag line="2" name="author" description="Timothy J. Warren"/>
|
||||
<tag line="2" name="copyright" description="Copyright (c) 2011 - 2012"/>
|
||||
<tag line="2" name="link" description="https://github.com/timw4mail/miniMVC" link="https://github.com/timw4mail/miniMVC"/>
|
||||
<tag line="2" name="license" description="http://philsturgeon.co.uk/code/dbad-license"/>
|
||||
</docblock>
|
||||
<include line="396" type="Require Once" package="Default">
|
||||
<name>db/autoload.php</name>
|
||||
</include>
|
||||
<include line="399" type="Require Once" package="Default">
|
||||
<name>core/miniMVC.php</name>
|
||||
</include>
|
||||
<function namespace="default" line="32" package="miniMVC">
|
||||
<name>shutdown</name>
|
||||
<type>function</type>
|
||||
<docblock line="25">
|
||||
<description><![CDATA[Function to run on script shutdown
|
||||
-used to catch most fatal errors, and
|
||||
display them cleanly]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="25" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="64" package="miniMVC">
|
||||
<name>load_file</name>
|
||||
<type>function</type>
|
||||
<docblock line="57">
|
||||
<description><![CDATA[Function to search through the tree to find the necessary file]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="57" name="param" description="" type="string" variable="$file">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="57" name="param" description="" type="string" variable="$curr_path">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="57" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="64">
|
||||
<name>$file</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="64">
|
||||
<name>$curr_path</name>
|
||||
<default><![CDATA[""]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="99" package="miniMVC">
|
||||
<name>on_error</name>
|
||||
<type>function</type>
|
||||
<docblock line="90">
|
||||
<description><![CDATA[Custom error handler]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="90" name="param" description="" type="int" variable="$severity">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="string" variable="$message">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="string" variable="$filepath">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="90" name="param" description="" type="int" variable="$line">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
<tag line="90" name="return" description="" type="\ErrorException">
|
||||
<type by_reference="false">\ErrorException</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="99">
|
||||
<name>$severity</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$message</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$filepath</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="99">
|
||||
<name>$line</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="112" package="miniMVC">
|
||||
<name>on_exception</name>
|
||||
<type>function</type>
|
||||
<docblock line="106">
|
||||
<description><![CDATA[Custom exception handlererror_get_last]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="106" name="param" description="" type="\Exception" variable="$exception">
|
||||
<type by_reference="false">\Exception</type>
|
||||
</tag>
|
||||
<tag line="106" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="112">
|
||||
<name>$exception</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="134" package="miniMVC">
|
||||
<name>is_like_array</name>
|
||||
<type>function</type>
|
||||
<docblock line="128">
|
||||
<description><![CDATA[Utility function to check if a variable is set, and is an array or object]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="128" name="param" description="" type="mixed" variable="$var">
|
||||
<type by_reference="false">mixed</type>
|
||||
</tag>
|
||||
<tag line="128" name="return" description="" type="bool">
|
||||
<type by_reference="false">bool</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="134">
|
||||
<name>$var</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="151" package="miniMVC">
|
||||
<name>show_404</name>
|
||||
<type>function</type>
|
||||
<docblock line="146">
|
||||
<description><![CDATA[General 404 function]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="146" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="175" package="miniMVC">
|
||||
<name>show_error</name>
|
||||
<type>function</type>
|
||||
<docblock line="169">
|
||||
<description><![CDATA[Fatal Error page function]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="169" name="param" description="" type="string" variable="$message">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="169" name="param" description="" type="int" variable="$status_code">
|
||||
<type by_reference="false">int</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="175">
|
||||
<name>$message</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="175">
|
||||
<name>$status_code</name>
|
||||
<default><![CDATA[null]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="200" package="miniMVC">
|
||||
<name>controller_methods</name>
|
||||
<type>function</type>
|
||||
<docblock line="194">
|
||||
<description><![CDATA[Returns routable methods for the specified controller class]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="194" name="param" description="" type="string" variable="$controller">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="194" name="return" description="" type="array">
|
||||
<type by_reference="false">array</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="200">
|
||||
<name>$controller</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="218" package="miniMVC">
|
||||
<name>route</name>
|
||||
<type>function</type>
|
||||
<docblock line="213">
|
||||
<description><![CDATA[Calls the appropriate module/controller/function based on the url]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="213" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
</function>
|
||||
<function namespace="default" line="342" package="miniMVC">
|
||||
<name>site_url</name>
|
||||
<type>function</type>
|
||||
<docblock line="336">
|
||||
<description><![CDATA[Returns a full url from a url segment]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="336" name="param" description="" type="string" variable="$segment">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="336" name="return" description="" type="string">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="342">
|
||||
<name>$segment</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="356" package="miniMVC">
|
||||
<name>to_string</name>
|
||||
<type>function</type>
|
||||
<docblock line="349">
|
||||
<description><![CDATA[Prints out the contents of the object]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="349" name="param" description="" type="\object/array" variable="$data">
|
||||
<type by_reference="false">\object/array</type>
|
||||
</tag>
|
||||
<tag line="349" name="param" description="" type="string" variable="$method">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="349" name="return" description="" type="string">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="356">
|
||||
<name>$data</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
<argument line="356">
|
||||
<name>$method</name>
|
||||
<default><![CDATA['print_r']]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
<function namespace="default" line="390" package="miniMVC">
|
||||
<name>do_include</name>
|
||||
<type>function</type>
|
||||
<docblock line="384">
|
||||
<description><![CDATA[Array_map callback to load a folder of classes at once]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="384" name="param" description="" type="string" variable="$path">
|
||||
<type by_reference="false">string</type>
|
||||
</tag>
|
||||
<tag line="384" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
<argument line="390">
|
||||
<name>$path</name>
|
||||
<default><![CDATA[]]></default>
|
||||
<type/>
|
||||
</argument>
|
||||
</function>
|
||||
</file>
|
||||
<file path="index.php" hash="a6fec7a10150d40748e88987715e6510" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -6888,7 +6967,7 @@ Used for outputing HTML]]></description>
|
||||
</method>
|
||||
</class>
|
||||
</file>
|
||||
<file path="modules/welcome/controllers/welcome.php" hash="7c35135fe3c1510d57e332e337d640e6" package="miniMVC">
|
||||
<file path="modules/welcome/controllers/welcome.php" hash="b46fff4b3fd55129850e8edff54a75f5" package="miniMVC">
|
||||
<docblock line="2">
|
||||
<description><![CDATA[MiniMVC]]></description>
|
||||
<long-description><![CDATA[<p>Convention-based micro-framework for PHP</p>]]></long-description>
|
||||
@ -6930,13 +7009,13 @@ Used for outputing HTML]]></description>
|
||||
</tag>
|
||||
</docblock>
|
||||
</method>
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="50" package="">
|
||||
<method final="false" abstract="false" static="false" visibility="public" namespace="default" line="51" package="">
|
||||
<name>php</name>
|
||||
<type>function</type>
|
||||
<docblock line="45">
|
||||
<docblock line="46">
|
||||
<description><![CDATA[welcome/php route]]></description>
|
||||
<long-description><![CDATA[]]></long-description>
|
||||
<tag line="45" name="return" description="" type="void">
|
||||
<tag line="46" name="return" description="" type="void">
|
||||
<type by_reference="false">void</type>
|
||||
</tag>
|
||||
</docblock>
|
||||
@ -6952,6 +7031,7 @@ Used for outputing HTML]]></description>
|
||||
</package>
|
||||
<package name="miniMVC" full_name="miniMVC">
|
||||
<package name="App" full_name="miniMVC\App"/>
|
||||
<package name="Libraries" full_name="miniMVC\Libraries"/>
|
||||
<package name="System" full_name="miniMVC\System"/>
|
||||
</package>
|
||||
<namespace name="default" full_name="default"/>
|
||||
|
@ -38,8 +38,9 @@ class Welcome extends MM_Controller {
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$output = $this->page->set_message('info', "This is just a test message", TRUE);
|
||||
$this->page->output_string($output);
|
||||
$this->page->build_header();
|
||||
$output = $this->page->set_message('info', "This is just a test message");
|
||||
$this->page->build_footer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 31ba0881ea6088c6b141d6b75d6f2f302e61585c
|
@ -396,7 +396,7 @@ function do_include($path)
|
||||
require_once(MM_SYS_PATH.'db/autoload.php');
|
||||
|
||||
// Load system libraries
|
||||
require_once(MM_SYS_PATH.'miniMVC.php');
|
||||
array_map('do_include', glob(MM_SYS_PATH.'*.php'));
|
||||
require_once(MM_SYS_PATH.'core/miniMVC.php');
|
||||
array_map('do_include', glob(MM_SYS_PATH.'core/*.php'));
|
||||
|
||||
// End of common.php
|
@ -308,22 +308,10 @@ class miniMVC extends MM {
|
||||
* Method to load classes into the singleton
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return void
|
||||
*/
|
||||
public function load_class($name, $type='class')
|
||||
public function load_class($name)
|
||||
{
|
||||
switch($type)
|
||||
{
|
||||
default:
|
||||
$path = MM_APP_PATH . "classes/{$name}.php";
|
||||
break;
|
||||
|
||||
case "sys":
|
||||
$path = MM_SYS_PATH . "{$name}.php";
|
||||
break;
|
||||
}
|
||||
|
||||
// In a subdirectory? No problem
|
||||
if (strpos("/", $name) !== FALSE)
|
||||
{
|
||||
@ -331,6 +319,16 @@ class miniMVC extends MM {
|
||||
$name = $n[count($n) -1];
|
||||
}
|
||||
|
||||
// Try system library first, then app library
|
||||
$path = MM_SYS_PATH . "libraries/{$name}.php";
|
||||
$name = 'MM_'.$name;
|
||||
|
||||
if ( ! is_file($path))
|
||||
{
|
||||
$path = MM_APP_PATH . "classes/{$name}.php";
|
||||
$name = str_replace('MM_', '', $name);
|
||||
}
|
||||
|
||||
$class = "{$name}";
|
||||
|
||||
// Load the class file if need be
|
||||
@ -345,10 +343,13 @@ class miniMVC extends MM {
|
||||
// Create the object, and add it to the current miniMVC object
|
||||
if (class_exists($class, FALSE))
|
||||
{
|
||||
// Remove MM_ prefix from name
|
||||
$name = str_replace('MM_', '', $name);
|
||||
|
||||
if ( ! isset($this->$name))
|
||||
{
|
||||
// Call a singleton, if the get_instance method exists
|
||||
if (is_callable(array($class, 'get_instance')))
|
||||
if (method_exists($class, 'get_instance'))
|
||||
{
|
||||
$this->$name =& $class::get_instance();
|
||||
return;
|
@ -1,83 +0,0 @@
|
||||
# Query
|
||||
|
||||
A query builder/abstraction layer, using prepared queries for security.
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/timw4mail/Query.png)](http://travis-ci.org/timw4mail/Query)
|
||||
|
||||
## Requirements
|
||||
* Pdo extensions for the databases you wish to use (unless it's Firebird, in which case, the interbase extension is required)
|
||||
* PHP 5.2+
|
||||
|
||||
## Databases Supported
|
||||
|
||||
* Firebird
|
||||
* MySQL
|
||||
* PostgreSQL
|
||||
* SQLite
|
||||
* Others, via ODBC
|
||||
|
||||
## Including Query in your application
|
||||
|
||||
To include Query in your PHP project, just include the `autoload.php` file. This will automatically load the classes that are supported by the current PHP installation.
|
||||
|
||||
|
||||
## Connecting
|
||||
|
||||
Create a connection array or object similar to this:
|
||||
|
||||
<?php
|
||||
|
||||
$params = array(
|
||||
'type' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'user' => 'root',
|
||||
'pass' => '',
|
||||
'port' => '3306',
|
||||
'database' => 'test_db',
|
||||
|
||||
// Only required
|
||||
// SQLite or Firebird
|
||||
'file' => '/path/to/db/file',
|
||||
);
|
||||
|
||||
$db = new Query_Builder($params);
|
||||
|
||||
The parameters required depend on the database.
|
||||
|
||||
### Running Queries
|
||||
Query uses the same interface as CodeIgniter's [Active Record class](http://codeigniter.com/user_guide/database/active_record.html). However, it does not implement the `insert_batch` or `update_batch` methods.
|
||||
|
||||
####You can also run queries manually.
|
||||
|
||||
To run a prepared statement, call
|
||||
`$db->prepare_execute($sql, $params)`.
|
||||
|
||||
To run a plain query, `$db->query($sql)`
|
||||
|
||||
### Retrieving Results:
|
||||
|
||||
An example of a moderately complex query:
|
||||
|
||||
$query = $db->select('id, key as k, val')
|
||||
->from('table t')
|
||||
->where('k >', 3)
|
||||
->or_where('id !=' 5)
|
||||
->order_by('val', 'DESC')
|
||||
->limit(3, 1)
|
||||
->get();
|
||||
|
||||
This will generate a query similar to (with this being the output for a Postgres database):
|
||||
|
||||
SELECT "id", "key" AS "k", "val"
|
||||
FROM "table" "t"
|
||||
WHERE "k" > ?
|
||||
OR "id" != ?
|
||||
ORDER BY "val" DESC
|
||||
LIMIT 3 OFFSET 1
|
||||
|
||||
|
||||
To retreive the results of a query, use the PDO method [fetch](http://php.net/manual/en/pdostatement.fetch.php) and/or [fetchAll](http://php.net/manual/en/pdostatement.fetchall.php).
|
||||
|
||||
$query = $db->get('table_name');
|
||||
|
||||
$results = $query->fetchAll(PDO::FETCH_ASSOC);
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
<title>Query</title>
|
||||
<parser>
|
||||
<target>docs</target>
|
||||
</parser>
|
||||
<transformer>
|
||||
<target>docs</target>
|
||||
</transformer>
|
||||
<transformations>
|
||||
<template name="responsive" />
|
||||
</transformations>
|
||||
<files>
|
||||
<directory>.</directory>
|
||||
<directory>tests</directory>
|
||||
<ignore>tests/*</ignore>
|
||||
</files>
|
||||
</phpdoc>
|
@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
/**
|
||||
* CoreTest class - Compatibility and core functionality tests
|
||||
*
|
||||
* @extends UnitTestCase
|
||||
*/
|
||||
class CoreTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* __construct function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TestPHPVersion function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function TestPHPVersion()
|
||||
{
|
||||
$this->assertTrue(version_compare(PHP_VERSION, "5.2", "ge"));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TestHasPDO function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function TestHasPDO()
|
||||
{
|
||||
// PDO class exists
|
||||
$this->assertTrue(class_exists('PDO'));
|
||||
|
||||
|
||||
// Make sure at least one of the supported drivers is enabled
|
||||
$supported = array(
|
||||
'mysql',
|
||||
'pgsql',
|
||||
'odbc',
|
||||
'sqlite',
|
||||
);
|
||||
|
||||
$drivers = pdo_drivers();
|
||||
|
||||
$num_supported = count(array_intersect($drivers, $supported));
|
||||
|
||||
$this->assertTrue($num_supported > 0);
|
||||
}
|
||||
}
|
@ -1,430 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Query builder parent test class
|
||||
*/
|
||||
abstract class QBTest extends UnitTestCase {
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Get Tests
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGet()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetLimit()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->get('create_test', 2);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetLimitSkip()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->get('create_test', 2, 1);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetWhere()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->get_where('create_test', array('id !=' => 1), 2, 1);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestHaving()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id')
|
||||
->from('create_test')
|
||||
->group_by('id')
|
||||
->having(array('id >' => 1))
|
||||
->having('id !=', 3)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestOrHaving()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id')
|
||||
->from('create_test')
|
||||
->group_by('id')
|
||||
->having(array('id >' => 1))
|
||||
->or_having('id !=', 3)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetViews()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$this->assertTrue(is_array($this->db->get_views()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Select Tests
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectWhereGet()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->where('id >', 1)
|
||||
->where('id <', 900)
|
||||
->get('create_test', 2, 1);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectWhereGet2()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->where('id !=', 1)
|
||||
->get('create_test', 2, 1);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectMax()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select_max('id', 'di')
|
||||
->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectMin()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select_min('id', 'di')
|
||||
->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectAvg()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select_avg('id', 'di')
|
||||
->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectSum()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select_sum('id', 'di')
|
||||
->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectDistinct()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select_sum('id', 'di')
|
||||
->distinct()
|
||||
->get('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectGet()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->get('create_test', 2, 1);
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectFromGet()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test ct')
|
||||
->where('id >', 1)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSelectFromLimitGet()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test ct')
|
||||
->where('id >', 1)
|
||||
->limit(3)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Query modifier tests
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestOrderBy()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test')
|
||||
->where('id >', 0)
|
||||
->where('id <', 9000)
|
||||
->order_by('id', 'DESC')
|
||||
->order_by('k', 'ASC')
|
||||
->limit(5,2)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestOrderByRandom()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test')
|
||||
->where('id >', 0)
|
||||
->where('id <', 9000)
|
||||
->order_by('id', 'rand')
|
||||
->limit(5,2)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGroupBy()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test')
|
||||
->where('id >', 0)
|
||||
->where('id <', 9000)
|
||||
->group_by('k')
|
||||
->group_by('id')
|
||||
->group_by('val')
|
||||
->order_by('id', 'DESC')
|
||||
->order_by('k', 'ASC')
|
||||
->limit(5,2)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestOrWhere()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test')
|
||||
->where(' id ', 1)
|
||||
->or_where('key >', 0)
|
||||
->limit(2, 1)
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestLike()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->from('create_test')
|
||||
->like('key', 'og')
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestJoin()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->from('create_test')
|
||||
->join('create_join cj', 'cj.id = create_test.id')
|
||||
->get();
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! DB update tests
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestInsert()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->set('id', 4)
|
||||
->set('key', 4)
|
||||
->set('val', 5)
|
||||
->insert('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestUpdate()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->set('id', 4)
|
||||
->set('key', 'gogle')
|
||||
->set('val', 'non-word')
|
||||
->where('id', 4)
|
||||
->update('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestDelete()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->where('id', 4)->delete('create_test');
|
||||
|
||||
$this->assertIsA($query, 'PDOStatement');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ! Non-data read queries
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCountAll()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
$query = $this->db->count_all('create_test');
|
||||
|
||||
$this->assertTrue(is_numeric($query));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCountAllResults()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
$query = $this->db->count_all_results('create_test');
|
||||
|
||||
$this->assertTrue(is_numeric($query));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCountAllResults2()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$query = $this->db->select('id, key as k, val')
|
||||
->from('create_test')
|
||||
->where(' id ', 1)
|
||||
->or_where('key >', 0)
|
||||
->limit(2, 1)
|
||||
->count_all_results();
|
||||
|
||||
$this->assertTrue(is_numeric($query));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestNumRows()
|
||||
{
|
||||
$query = $this->db->get('create_test');
|
||||
|
||||
$this->assertTrue(is_numeric($this->db->num_rows()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// End of db_qb_test.php
|
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parent Database Test Class
|
||||
*/
|
||||
abstract class DBTest extends UnitTestCase {
|
||||
|
||||
abstract public function TestConnection();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->db = NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTables()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$tables = $this->db->get_tables();
|
||||
$this->assertTrue(is_array($tables));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSystemTables()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$tables = $this->db->get_system_tables();
|
||||
|
||||
$this->assertTrue(is_array($tables));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTransaction()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$res = $this->db->beginTransaction();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestBackupData()
|
||||
{
|
||||
$this->assertTrue(is_string($this->db->util->backup_data()));
|
||||
}
|
||||
}
|
||||
// End of db_test.php
|
@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Settings Class Test Class
|
||||
*/
|
||||
class SettingsTest extends UnitTestCase {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->settings =& Settings::get_instance();
|
||||
|
||||
// Make sure to delete 'foo' if it exists
|
||||
$this->settings->remove_db('foo');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestExists()
|
||||
{
|
||||
$this->assertIsA($this->settings, 'Settings');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetEmptyDBs()
|
||||
{
|
||||
$this->assertTrue(is_object($this->settings->get_dbs()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetNull()
|
||||
{
|
||||
$this->assertFalse(isset($this->settings->foo));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSet()
|
||||
{
|
||||
$bar = $this->settings->foo = 'bar';
|
||||
|
||||
$this->assertEqual('bar', $bar);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGet()
|
||||
{
|
||||
$this->assertEqual('bar', $this->settings->foo);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestSetDBProperty()
|
||||
{
|
||||
$res = $this->settings->__set('dbs', 2);
|
||||
$this->assertFalse($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetEmptyDB()
|
||||
{
|
||||
$this->assertFalse($this->settings->get_db('foo'));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestAddDB()
|
||||
{
|
||||
$this->settings->add_db('foo', array());
|
||||
|
||||
$db = $this->settings->get_db('foo');
|
||||
|
||||
$this->assertTrue(isset($db));
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Firebird Query Builder Tests
|
||||
*/
|
||||
class FirebirdQBTest extends QBTest {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$dbpath = QTEST_DIR.QDS.'db_files'.QDS.'FB_TEST_DB.FDB';
|
||||
|
||||
// Test the query builder
|
||||
$params = new Stdclass();
|
||||
$params->type = 'firebird';
|
||||
$params->file = $dbpath;
|
||||
$params->host = 'localhost';
|
||||
$params->user = 'sysdba';
|
||||
$params->pass = 'masterkey';
|
||||
$this->db = new Query_Builder($params);
|
||||
|
||||
// echo '<hr /> Firebird Queries <hr />';
|
||||
}
|
||||
}
|
@ -1,221 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* FirebirdTest class.
|
||||
*
|
||||
* @extends UnitTestCase
|
||||
*/
|
||||
class FirebirdTest extends DBTest {
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$dbpath = QTEST_DIR.QDS.'db_files'.QDS.'FB_TEST_DB.FDB';
|
||||
|
||||
// Test the db driver directly
|
||||
$this->db = new Firebird('localhost:'.$dbpath);
|
||||
$this->tables = $this->db->get_tables();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->db);
|
||||
unset($this->tables);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestConnection()
|
||||
{
|
||||
$this->assertIsA($this->db, 'Firebird');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTables()
|
||||
{
|
||||
$tables = $this->tables;
|
||||
$this->assertTrue(is_array($tables));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSystemTables()
|
||||
{
|
||||
$only_system = TRUE;
|
||||
|
||||
$tables = $this->db->get_system_tables();
|
||||
|
||||
foreach($tables as $t)
|
||||
{
|
||||
if(stripos($t, 'rdb$') !== 0 && stripos($t, 'mon$') !== 0)
|
||||
{
|
||||
$only_system = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue($only_system);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*public function TestCreateTable()
|
||||
{
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->sql->create_table('create_join', array(
|
||||
'id' => 'SMALLINT',
|
||||
'key' => 'VARCHAR(64)',
|
||||
'val' => 'BLOB SUB_TYPE TEXT'
|
||||
));
|
||||
$this->db->query($sql);
|
||||
|
||||
//This test fails for an unknown reason, when clearly the table exists
|
||||
//Reset
|
||||
$this->tearDown();
|
||||
$this->setUp();
|
||||
|
||||
//Check
|
||||
$table_exists = (bool)in_array('create_test', $this->tables);
|
||||
|
||||
echo "create_test exists :".(int)$table_exists.'<br />';
|
||||
|
||||
$this->assertTrue($table_exists);
|
||||
}*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestTruncate()
|
||||
{
|
||||
$this->db->truncate('create_test');
|
||||
|
||||
$this->assertTrue($this->db->affected_rows() > 0);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCommitTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (10, 12, 14)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->commit();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestRollbackTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (182, 96, 43)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->rollback();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPreparedStatements()
|
||||
{
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute(array(1,"booger's", "Gross"));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPrepareExecute()
|
||||
{
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$this->db->prepare_execute($sql, array(
|
||||
2, "works", 'also?'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPrepareQuery()
|
||||
{
|
||||
$this->assertFalse($this->db->prepare_query('', array()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*public function TestDeleteTable()
|
||||
{
|
||||
//Attempt to delete the table
|
||||
$sql = $this->db->sql->delete_table('create_test');
|
||||
$this->db->query($sql);
|
||||
|
||||
//Reset
|
||||
$this->tearDown();
|
||||
$this->setUp();
|
||||
|
||||
//Check
|
||||
$table_exists = in_array('create_test', $this->tables);
|
||||
$this->assertFalse($table_exists);
|
||||
}*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSequences()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_sequences()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetProcedures()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_procedures()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetFunctions()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_functions()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTriggers()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_triggers()));
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class MySQLQBTest extends QBTest {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Attempt to connect, if there is a test config file
|
||||
if (is_file(QBASE_DIR . "test_config.json"))
|
||||
{
|
||||
$params = json_decode(file_get_contents(QBASE_DIR . "test_config.json"));
|
||||
$params = $params->mysql;
|
||||
$params->type = "mysql";
|
||||
|
||||
$this->db = new Query_Builder($params);
|
||||
|
||||
// echo '<hr /> MySQL Queries <hr />';
|
||||
}
|
||||
elseif (($var = getenv('CI')))
|
||||
{
|
||||
$params = array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'user' => 'root',
|
||||
'pass' => NULL,
|
||||
'type' => 'mysql'
|
||||
);
|
||||
|
||||
$this->db = new Query_Builder($params);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestExists()
|
||||
{
|
||||
$this->assertTrue(in_array('mysql', pdo_drivers()));
|
||||
}
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* MySQLTest class.
|
||||
*
|
||||
* @extends UnitTestCase
|
||||
*/
|
||||
class MySQLTest extends DBTest {
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
// Attempt to connect, if there is a test config file
|
||||
if (is_file(QBASE_DIR . "test_config.json"))
|
||||
{
|
||||
$params = json_decode(file_get_contents(QBASE_DIR . "test_config.json"), TRUE);
|
||||
$params = $params['mysql'];
|
||||
|
||||
$this->db = new MySQL("host={$params['host']};port={$params['port']};dbname={$params['database']}", $params['user'], $params['pass']);
|
||||
}
|
||||
elseif (($var = getenv('CI')))
|
||||
{
|
||||
$this->db = new MySQL('host=127.0.0.1;port=3306;dbname=test', 'root');
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestExists()
|
||||
{
|
||||
$this->assertTrue(in_array('mysql', pdo_drivers()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestConnection()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$this->assertIsA($this->db, 'MySQL');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTable()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_test',
|
||||
array(
|
||||
'id' => 'int(10)',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
|
||||
$this->db->query($sql);
|
||||
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_join',
|
||||
array(
|
||||
'id' => 'int(10)',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
$this->db->query($sql);
|
||||
|
||||
//Check
|
||||
$dbs = $this->db->get_tables();
|
||||
|
||||
$this->assertTrue(in_array('create_test', $dbs));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestTruncate()
|
||||
{
|
||||
$this->db->truncate('create_test');
|
||||
$this->db->truncate('create_join');
|
||||
|
||||
$ct_query = $this->db->query('SELECT * FROM create_test');
|
||||
$cj_query = $this->db->query('SELECT * FROM create_join');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPreparedStatements()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$sql = <<<SQL
|
||||
INSERT INTO `create_test` (`id`, `key`, `val`)
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$statement = $this->db->prepare_query($sql, array(1,"boogers", "Gross"));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPrepareExecute()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$sql = <<<SQL
|
||||
INSERT INTO `create_test` (`id`, `key`, `val`)
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$this->db->prepare_execute($sql, array(
|
||||
2, "works", 'also?'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCommitTransaction()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO `create_test` (`id`, `key`, `val`) VALUES (10, 12, 14)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->commit();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestRollbackTransaction()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO `create_test` (`id`, `key`, `val`) VALUES (182, 96, 43)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->rollback();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSchemas()
|
||||
{
|
||||
$this->assertFalse($this->db->get_schemas());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetsProcedures()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_procedures()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTriggers()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_triggers()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSequences()
|
||||
{
|
||||
$this->assertFalse($this->db->get_sequences());
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class PgSQLQBTest extends QBTest {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Attempt to connect, if there is a test config file
|
||||
if (is_file(QBASE_DIR . "test_config.json"))
|
||||
{
|
||||
$params = json_decode(file_get_contents(QBASE_DIR . "test_config.json"));
|
||||
$params = $params->pgsql;
|
||||
$params->type = "pgsql";
|
||||
|
||||
$this->db = new Query_Builder($params);
|
||||
|
||||
// echo '<hr /> Postgres Queries <hr />';
|
||||
|
||||
}
|
||||
elseif (($var = getenv('CI')))
|
||||
{
|
||||
$params = array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '5432',
|
||||
'database' => 'test',
|
||||
'user' => 'postgres',
|
||||
'pass' => '',
|
||||
'type' => 'pgsql'
|
||||
);
|
||||
|
||||
$this->db = new Query_Builder($params);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestExists()
|
||||
{
|
||||
$this->assertTrue(in_array('pgsql', pdo_drivers()));
|
||||
}
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* PgTest class.
|
||||
*
|
||||
* @extends UnitTestCase
|
||||
*/
|
||||
class PgTest extends DBTest {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
// Attempt to connect, if there is a test config file
|
||||
if (is_file(QBASE_DIR . "test_config.json"))
|
||||
{
|
||||
$params = json_decode(file_get_contents(QBASE_DIR . "test_config.json"));
|
||||
$params = $params->pgsql;
|
||||
|
||||
$this->db = new PgSQL("host={$params->host};port={$params->port};dbname={$params->database}", $params->user, $params->pass);
|
||||
}
|
||||
elseif (($var = getenv('CI')))
|
||||
{
|
||||
$this->db = new PgSQL('host=127.0.0.1;port=5432;dbname=test', 'postgres');
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestExists()
|
||||
{
|
||||
$this->assertTrue(in_array('pgsql', pdo_drivers()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestConnection()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$this->assertIsA($this->db, 'PgSQL');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTable()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
// Drop the table(s) if they exist
|
||||
$sql = 'DROP TABLE IF EXISTS "create_test"';
|
||||
$this->db->query($sql);
|
||||
$sql = 'DROP TABLE IF EXISTS "create_join"';
|
||||
$this->db->query($sql);
|
||||
|
||||
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_test',
|
||||
array(
|
||||
'id' => 'integer',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
|
||||
$this->db->query($sql);
|
||||
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_join',
|
||||
array(
|
||||
'id' => 'integer',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
$this->db->query($sql);
|
||||
|
||||
//echo $sql.'<br />';
|
||||
|
||||
//Reset
|
||||
unset($this->db);
|
||||
$this->setUp();
|
||||
|
||||
//Check
|
||||
$dbs = $this->db->get_tables();
|
||||
$this->assertTrue(in_array('create_test', $dbs));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestTruncate()
|
||||
{
|
||||
$this->db->truncate('create_test');
|
||||
$this->db->truncate('create_join');
|
||||
|
||||
$ct_query = $this->db->query('SELECT * FROM create_test');
|
||||
$cj_query = $this->db->query('SELECT * FROM create_join');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPreparedStatements()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$statement = $this->db->prepare_query($sql, array(1,"boogers", "Gross"));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPrepareExecute()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$this->db->prepare_execute($sql, array(
|
||||
2, "works", 'also?'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCommitTransaction()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (10, 12, 14)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->commit();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestRollbackTransaction()
|
||||
{
|
||||
if (empty($this->db)) return;
|
||||
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (182, 96, 43)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->rollback();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSchemas()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_schemas()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSequences()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_sequences()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetsProcedures()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_procedures()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTriggers()
|
||||
{
|
||||
$this->assertTrue(is_array($this->db->get_triggers()));
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class for testing Query Builder with SQLite
|
||||
*/
|
||||
class SQLiteQBTest extends QBTest {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$path = QTEST_DIR.QDS.'db_files'.QDS.'test_sqlite.db';
|
||||
$params = new Stdclass();
|
||||
$params->type = 'sqlite';
|
||||
$params->file = $path;
|
||||
$params->host = 'localhost';
|
||||
$this->db = new Query_Builder($params);
|
||||
|
||||
// echo '<hr /> SQLite Queries <hr />';
|
||||
}
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* OpenSQLManager
|
||||
*
|
||||
* Free Database manager for Open Source Databases
|
||||
*
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/OpenSQLManager
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* SQLiteTest class.
|
||||
*
|
||||
* @extends UnitTestCase
|
||||
*/
|
||||
class SQLiteTest extends UnitTestCase {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$path = QTEST_DIR.QDS.'db_files'.QDS.'test_sqlite.db';
|
||||
$this->db = new SQLite($path);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->db);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestConnection()
|
||||
{
|
||||
$this->assertIsA($this->db, 'SQLite');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetTables()
|
||||
{
|
||||
$tables = $this->db->get_tables();
|
||||
$this->assertTrue(is_array($tables));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSystemTables()
|
||||
{
|
||||
$tables = $this->db->get_system_tables();
|
||||
|
||||
$this->assertTrue(is_array($tables));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCreateTable()
|
||||
{
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_test',
|
||||
array(
|
||||
'id' => 'INTEGER',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
$this->db->query($sql);
|
||||
|
||||
//Attempt to create the table
|
||||
$sql = $this->db->util->create_table('create_join',
|
||||
array(
|
||||
'id' => 'INTEGER',
|
||||
'key' => 'TEXT',
|
||||
'val' => 'TEXT',
|
||||
),
|
||||
array(
|
||||
'id' => 'PRIMARY KEY'
|
||||
)
|
||||
);
|
||||
$this->db->query($sql);
|
||||
|
||||
//Check
|
||||
$dbs = $this->db->get_tables();
|
||||
|
||||
$this->assertTrue(in_array('create_test', $dbs));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestTruncate()
|
||||
{
|
||||
$this->db->truncate('create_test');
|
||||
$this->assertIsA($this->db->affected_rows(), 'int');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPreparedStatements()
|
||||
{
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$statement = $this->db->prepare_query($sql, array(1,"boogers", "Gross"));
|
||||
|
||||
$statement->execute();
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestPrepareExecute()
|
||||
{
|
||||
$sql = <<<SQL
|
||||
INSERT INTO "create_test" ("id", "key", "val")
|
||||
VALUES (?,?,?)
|
||||
SQL;
|
||||
$this->db->prepare_execute($sql, array(
|
||||
2, "works", 'also?'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestCommitTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (10, 12, 14)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->commit();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestRollbackTransaction()
|
||||
{
|
||||
$res = $this->db->beginTransaction();
|
||||
|
||||
$sql = 'INSERT INTO "create_test" ("id", "key", "val") VALUES (182, 96, 43)';
|
||||
$this->db->query($sql);
|
||||
|
||||
$res = $this->db->rollback();
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// This is really time intensive ! Run only when needed
|
||||
/*public function TestDeleteTable()
|
||||
{
|
||||
//Make sure the table exists to delete
|
||||
$dbs = $this->db->get_tables();
|
||||
$this->assertTrue(isset($dbs['create_test']));
|
||||
|
||||
//Attempt to delete the table
|
||||
$sql = $this->db->sql->delete_table('create_test');
|
||||
$this->db->query($sql);
|
||||
|
||||
//Check
|
||||
$dbs = $this->db->get_tables();
|
||||
$this->assertFalse(in_array('create_test', $dbs));
|
||||
}*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetDBs()
|
||||
{
|
||||
$this->assertFalse($this->db->get_dbs());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public function TestGetSchemas()
|
||||
{
|
||||
$this->assertFalse($this->db->get_schemas());
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* Free Query Builder / Database Abstraction Layer
|
||||
*
|
||||
* @package Query
|
||||
* @author Timothy J. Warren
|
||||
* @copyright Copyright (c) 2012
|
||||
* @link https://github.com/aviat4ion/Query
|
||||
* @license http://philsturgeon.co.uk/code/dbad-license
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Unit test bootstrap - Using php simpletest
|
||||
*/
|
||||
define('QTEST_DIR', dirname(__FILE__));
|
||||
define('QBASE_DIR', str_replace(basename(QTEST_DIR), '', QTEST_DIR));
|
||||
define('QDS', DIRECTORY_SEPARATOR);
|
||||
|
||||
// Include simpletest
|
||||
// it has to be set in your php path, or put in the tests folder
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
// Include db classes
|
||||
require_once(QBASE_DIR . 'autoload.php');
|
||||
|
||||
// Require base testing classes
|
||||
require_once(QTEST_DIR . '/core/core.php');
|
||||
require_once(QTEST_DIR . '/core/settings.php');
|
||||
require_once(QTEST_DIR . '/core/db_test.php');
|
||||
require_once(QTEST_DIR . '/core/db_qb_test.php');
|
||||
|
||||
// Include db tests
|
||||
// Load db classes based on capability
|
||||
$src_path = QBASE_DIR.'drivers/';
|
||||
$test_path = QTEST_DIR.'/databases/';
|
||||
|
||||
foreach(pdo_drivers() as $d)
|
||||
{
|
||||
// PDO firebird isn't stable enough to
|
||||
// bother, so skip it.
|
||||
if ($d === 'firebird')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$src_dir = "{$test_path}{$d}";
|
||||
|
||||
if(is_dir($src_dir))
|
||||
{
|
||||
require_once("{$test_path}{$d}/{$d}.php");
|
||||
require_once("{$test_path}{$d}/{$d}-qb.php");
|
||||
}
|
||||
}
|
||||
|
||||
// Load Firebird if there is support
|
||||
if(function_exists('fbird_connect'))
|
||||
{
|
||||
require_once("{$test_path}/firebird/firebird.php");
|
||||
require_once("{$test_path}/firebird/firebird-qb.php");
|
||||
}
|
@ -1,399 +0,0 @@
|
||||
Simple Test interface changes
|
||||
=============================
|
||||
Because the SimpleTest tool set is still evolving it is likely that tests
|
||||
written with earlier versions will fail with the newest ones. The most
|
||||
dramatic changes are in the alpha releases. Here is a list of possible
|
||||
problems and their fixes...
|
||||
|
||||
assertText() no longer finds a string inside a <script> tag
|
||||
-----------------------------------------------------------
|
||||
The assertText() method is intended to match only visible,
|
||||
human-readable text on the web page. Therefore, the contents of script
|
||||
tags should not be matched by this assertion. However there was a bug
|
||||
in the text normalisation code of simpletest which meant that <script>
|
||||
tags spanning multiple lines would not have their content stripped
|
||||
out. If you want to check the content of a <script> tag, use
|
||||
assertPattern(), or write a custom expectation.
|
||||
|
||||
Overloaded method not working
|
||||
-----------------------------
|
||||
All protected and private methods had underscores
|
||||
removed. This means that any private/protected methods that
|
||||
you overloaded with those names need to be updated.
|
||||
|
||||
Fatal error: Call to undefined method Classname::classname()
|
||||
------------------------------------------------------------
|
||||
SimpleTest renamed all of its constructors from
|
||||
Classname to __construct; derived classes invoking
|
||||
their parent constructors should replace parent::Classname()
|
||||
with parent::__construct().
|
||||
|
||||
Custom CSS in HtmlReporter not being applied
|
||||
--------------------------------------------
|
||||
Batch rename of protected and private methods
|
||||
means that _getCss() was renamed to getCss().
|
||||
Please rename your method and it should work again.
|
||||
|
||||
setReturnReference() throws errors in E_STRICT
|
||||
----------------------------------------------
|
||||
Happens when an object is passed by reference.
|
||||
This also happens with setReturnReferenceAt().
|
||||
If you want to return objects then replace these
|
||||
with calls to returns() and returnsAt() with the
|
||||
same arguments. This change was forced in the 1.1
|
||||
version for E_STRICT compatibility.
|
||||
|
||||
assertReference() throws errors in E_STRICT
|
||||
-------------------------------------------
|
||||
Due to language restrictions you cannot compare
|
||||
both variables and objects in E_STRICT mode. Use
|
||||
assertSame() in this mode with objects. This change
|
||||
was forced the 1.1 version.
|
||||
|
||||
Cannot create GroupTest
|
||||
-----------------------
|
||||
The GroupTest has been renamed TestSuite (see below).
|
||||
It was removed completely in 1.1 in favour of this
|
||||
name.
|
||||
|
||||
No method getRelativeUrls() or getAbsoluteUrls()
|
||||
------------------------------------------------
|
||||
These methods were always a bit weird anyway, and
|
||||
the new parsing of the base tag makes them more so.
|
||||
They have been replaced with getUrls() instead. If
|
||||
you want the old functionality then simply chop
|
||||
off the current domain from getUrls().
|
||||
|
||||
Method setWildcard() removed in mocks
|
||||
-------------------------------------
|
||||
Even setWildcard() has been removed in 1.0.1beta now.
|
||||
If you want to test explicitely for a '*' string, then
|
||||
simply pass in new IdenticalExpectation('*') instead.
|
||||
|
||||
No method _getTest() on mocks
|
||||
-----------------------------
|
||||
This has finally been removed. It was a pretty esoteric
|
||||
flex point anyway. It was there to allow the mocks to
|
||||
work with other test tools, but no one does this.
|
||||
|
||||
No method assertError(), assertNoErrors(), swallowErrors()
|
||||
----------------------------------------------------------
|
||||
These have been deprecated in 1.0.1beta in favour of
|
||||
expectError() and expectException(). assertNoErrors() is
|
||||
redundant if you use expectError() as failures are now reported
|
||||
immediately.
|
||||
|
||||
No method TestCase::signal()
|
||||
----------------------------
|
||||
This has been deprecated in favour of triggering an error or
|
||||
throwing an exception. Deprecated as of 1.0.1beta.
|
||||
|
||||
No method TestCase::sendMessage()
|
||||
---------------------------------
|
||||
This has been deprecated as of 1.0.1beta.
|
||||
|
||||
Failure to connect now emits failures
|
||||
-------------------------------------
|
||||
It used to be that you would have to use the
|
||||
getTransferError() call on the web tester to see if
|
||||
there was a socket level error in a fetch. This check
|
||||
is now always carried out by the WebTestCase unless
|
||||
the fetch is prefaced with WebTestCase::ignoreErrors().
|
||||
The ignore directive only lasts for the next fetching
|
||||
action such as get() and click().
|
||||
|
||||
No method SimpleTestOptions::ignore()
|
||||
-------------------------------------
|
||||
This is deprecated in version 1.0.1beta and has been moved
|
||||
to SimpleTest::ignore() as that is more readable. In
|
||||
addition, parent classes are also ignored automatically.
|
||||
If you are using PHP5 you can skip this directive simply
|
||||
by marking your test case as abstract.
|
||||
|
||||
No method assertCopy()
|
||||
----------------------
|
||||
This is deprecated in 1.0.1 in favour of assertClone().
|
||||
The assertClone() method is slightly different in that
|
||||
the objects must be identical, but without being a
|
||||
reference. It is thus not a strict inversion of
|
||||
assertReference().
|
||||
|
||||
Constructor wildcard override has no effect in mocks
|
||||
----------------------------------------------------
|
||||
As of 1.0.1beta this is now set with setWildcard() instead
|
||||
of in the constructor.
|
||||
|
||||
No methods setStubBaseClass()/getStubBaseClass()
|
||||
------------------------------------------------
|
||||
As mocks are now used instead of stubs, these methods
|
||||
stopped working and are now removed as of the 1.0.1beta
|
||||
release. The mock objects may be freely used instead.
|
||||
|
||||
No method addPartialMockCode()
|
||||
------------------------------
|
||||
The ability to insert arbitrary partial mock code
|
||||
has been removed. This was a low value feature
|
||||
causing needless complications. It was removed
|
||||
in the 1.0.1beta release.
|
||||
|
||||
No method setMockBaseClass()
|
||||
----------------------------
|
||||
The ability to change the mock base class has been
|
||||
scheduled for removal and is deprecated since the
|
||||
1.0.1beta version. This was a rarely used feature
|
||||
except as a workaround for PHP5 limitations. As
|
||||
these limitations are being resolved it's hoped
|
||||
that the bundled mocks can be used directly.
|
||||
|
||||
No class Stub
|
||||
-------------
|
||||
Server stubs are deprecated from 1.0.1 as the mocks now
|
||||
have exactly the same interface. Just use mock objects
|
||||
instead.
|
||||
|
||||
No class SimpleTestOptions
|
||||
--------------------------
|
||||
This was replced by the shorter SimpleTest in 1.0.1beta1
|
||||
and is since deprecated.
|
||||
|
||||
No file simple_test.php
|
||||
-----------------------
|
||||
This was renamed test_case.php in 1.0.1beta to more accurately
|
||||
reflect it's purpose. This file should never be directly
|
||||
included in test suites though, as it's part of the
|
||||
underlying mechanics and has a tendency to be refactored.
|
||||
|
||||
No class WantedPatternExpectation
|
||||
---------------------------------
|
||||
This was deprecated in 1.0.1alpha in favour of the simpler
|
||||
name PatternExpectation.
|
||||
|
||||
No class NoUnwantedPatternExpectation
|
||||
-------------------------------------
|
||||
This was deprecated in 1.0.1alpha in favour of the simpler
|
||||
name NoPatternExpectation.
|
||||
|
||||
No method assertNoUnwantedPattern()
|
||||
-----------------------------------
|
||||
This has been renamed to assertNoPattern() in 1.0.1alpha and
|
||||
the old form is deprecated.
|
||||
|
||||
No method assertWantedPattern()
|
||||
-------------------------------
|
||||
This has been renamed to assertPattern() in 1.0.1alpha and
|
||||
the old form is deprecated.
|
||||
|
||||
No method assertExpectation()
|
||||
-----------------------------
|
||||
This was renamed as assert() in 1.0.1alpha and the old form
|
||||
has been deprecated.
|
||||
|
||||
No class WildcardExpectation
|
||||
----------------------------
|
||||
This was a mostly internal class for the mock objects. It was
|
||||
renamed AnythingExpectation to bring it closer to JMock and
|
||||
NMock in version 1.0.1alpha.
|
||||
|
||||
Missing UnitTestCase::assertErrorPattern()
|
||||
------------------------------------------
|
||||
This method is deprecated for version 1.0.1 onwards.
|
||||
This method has been subsumed by assertError() that can now
|
||||
take an expectation. Simply pass a PatternExpectation
|
||||
into assertError() to simulate the old behaviour.
|
||||
|
||||
No HTML when matching page elements
|
||||
-----------------------------------
|
||||
This behaviour has been switched to using plain text as if it
|
||||
were seen by the user of the browser. This means that HTML tags
|
||||
are suppressed, entities are converted and whitespace is
|
||||
normalised. This should make it easier to match items in forms.
|
||||
Also images are replaced with their "alt" text so that they
|
||||
can be matched as well.
|
||||
|
||||
No method SimpleRunner::_getTestCase()
|
||||
--------------------------------------
|
||||
This was made public as getTestCase() in 1.0RC2.
|
||||
|
||||
No method restartSession()
|
||||
--------------------------
|
||||
This was renamed to restart() in the WebTestCase, SimpleBrowser
|
||||
and the underlying SimpleUserAgent in 1.0RC2. Because it was
|
||||
undocumented anyway, no attempt was made at backward
|
||||
compatibility.
|
||||
|
||||
My custom test case ignored by tally()
|
||||
--------------------------------------
|
||||
The _assertTrue method has had it's signature changed due to a bug
|
||||
in the PHP 5.0.1 release. You must now use getTest() from within
|
||||
that method to get the test case. Mock compatibility with other
|
||||
unit testers is now deprecated as of 1.0.1alpha as PEAR::PHPUnit2
|
||||
should soon have mock support of it's own.
|
||||
|
||||
Broken code extending SimpleRunner
|
||||
----------------------------------
|
||||
This was replaced with SimpleScorer so that I could use the runner
|
||||
name in another class. This happened in RC1 development and there
|
||||
is no easy backward compatibility fix. The solution is simply to
|
||||
extend SimpleScorer instead.
|
||||
|
||||
Missing method getBaseCookieValue()
|
||||
-----------------------------------
|
||||
This was renamed getCurrentCookieValue() in RC1.
|
||||
|
||||
Missing files from the SimpleTest suite
|
||||
---------------------------------------
|
||||
Versions of SimpleTest prior to Beta6 required a SIMPLE_TEST constant
|
||||
to point at the SimpleTest folder location before any of the toolset
|
||||
was loaded. This is no longer documented as it is now unnecessary
|
||||
for later versions. If you are using an earlier version you may
|
||||
need this constant. Consult the documentation that was bundled with
|
||||
the release that you are using or upgrade to Beta6 or later.
|
||||
|
||||
No method SimpleBrowser::getCurrentUrl()
|
||||
--------------------------------------
|
||||
This is replaced with the more versatile showRequest() for
|
||||
debugging. It only existed in this context for version Beta5.
|
||||
Later versions will have SimpleBrowser::getHistory() for tracking
|
||||
paths through pages. It is renamed as getUrl() since 1.0RC1.
|
||||
|
||||
No method Stub::setStubBaseClass()
|
||||
----------------------------------
|
||||
This method has finally been removed in 1.0RC1. Use
|
||||
SimpleTestOptions::setStubBaseClass() instead.
|
||||
|
||||
No class CommandLineReporter
|
||||
----------------------------
|
||||
This was renamed to TextReporter in Beta3 and the deprecated version
|
||||
was removed in 1.0RC1.
|
||||
|
||||
No method requireReturn()
|
||||
-------------------------
|
||||
This was deprecated in Beta3 and is now removed.
|
||||
|
||||
No method expectCookie()
|
||||
------------------------
|
||||
This method was abruptly removed in Beta4 so as to simplify the internals
|
||||
until another mechanism can replace it. As a workaround it is necessary
|
||||
to assert that the cookie has changed by setting it before the page
|
||||
fetch and then assert the desired value.
|
||||
|
||||
No method clickSubmitByFormId()
|
||||
-------------------------------
|
||||
This method had an incorrect name as no button was involved. It was
|
||||
renamed to submitByFormId() in Beta4 and the old version deprecated.
|
||||
Now removed.
|
||||
|
||||
No method paintStart() or paintEnd()
|
||||
------------------------------------
|
||||
You should only get this error if you have subclassed the lower level
|
||||
reporting and test runner machinery. These methods have been broken
|
||||
down into events for test methods, events for test cases and events
|
||||
for group tests. The new methods are...
|
||||
|
||||
paintStart() --> paintMethodStart(), paintCaseStart(), paintGroupStart()
|
||||
paintEnd() --> paintMethodEnd(), paintCaseEnd(), paintGroupEnd()
|
||||
|
||||
This change was made in Beta3, ironically to make it easier to subclass
|
||||
the inner machinery. Simply duplicating the code you had in the previous
|
||||
methods should provide a temporary fix.
|
||||
|
||||
No class TestDisplay
|
||||
--------------------
|
||||
This has been folded into SimpleReporter in Beta3 and is now deprecated.
|
||||
It was removed in RC1.
|
||||
|
||||
No method WebTestCase::fetch()
|
||||
------------------------------
|
||||
This was renamed get() in Alpha8. It is removed in Beta3.
|
||||
|
||||
No method submit()
|
||||
------------------
|
||||
This has been renamed clickSubmit() in Beta1. The old method was
|
||||
removed in Beta2.
|
||||
|
||||
No method clearHistory()
|
||||
------------------------
|
||||
This method is deprecated in Beta2 and removed in RC1.
|
||||
|
||||
No method getCallCount()
|
||||
------------------------
|
||||
This method has been deprecated since Beta1 and has now been
|
||||
removed. There are now more ways to set expectations on counts
|
||||
and so this method should be unecessery. Removed in RC1.
|
||||
|
||||
Cannot find file *
|
||||
------------------
|
||||
The following public name changes have occoured...
|
||||
|
||||
simple_html_test.php --> reporter.php
|
||||
simple_mock.php --> mock_objects.php
|
||||
simple_unit.php --> unit_tester.php
|
||||
simple_web.php --> web_tester.php
|
||||
|
||||
The old names were deprecated in Alpha8 and removed in Beta1.
|
||||
|
||||
No method attachObserver()
|
||||
--------------------------
|
||||
Prior to the Alpha8 release the old internal observer pattern was
|
||||
gutted and replaced with a visitor. This is to trade flexibility of
|
||||
test case expansion against the ease of writing user interfaces.
|
||||
|
||||
Code such as...
|
||||
|
||||
$test = &new MyTestCase();
|
||||
$test->attachObserver(new TestHtmlDisplay());
|
||||
$test->run();
|
||||
|
||||
...should be rewritten as...
|
||||
|
||||
$test = &new MyTestCase();
|
||||
$test->run(new HtmlReporter());
|
||||
|
||||
If you previously attached multiple observers then the workaround
|
||||
is to run the tests twice, once with each, until they can be combined.
|
||||
For one observer the old method is simulated in Alpha 8, but is
|
||||
removed in Beta1.
|
||||
|
||||
No class TestHtmlDisplay
|
||||
------------------------
|
||||
This class has been renamed to HtmlReporter in Alpha8. It is supported,
|
||||
but deprecated in Beta1 and removed in Beta2. If you have subclassed
|
||||
the display for your own design, then you will have to extend this
|
||||
class (HtmlReporter) instead.
|
||||
|
||||
If you have accessed the event queue by overriding the notify() method
|
||||
then I am afraid you are in big trouble :(. The reporter is now
|
||||
carried around the test suite by the runner classes and the methods
|
||||
called directly. In the unlikely event that this is a problem and
|
||||
you don't want to upgrade the test tool then simplest is to write your
|
||||
own runner class and invoke the tests with...
|
||||
|
||||
$test->accept(new MyRunner(new MyReporter()));
|
||||
|
||||
...rather than the run method. This should be easier to extend
|
||||
anyway and gives much more control. Even this method is overhauled
|
||||
in Beta3 where the runner class can be set within the test case. Really
|
||||
the best thing to do is to upgrade to this version as whatever you were
|
||||
trying to achieve before should now be very much easier.
|
||||
|
||||
Missing set options method
|
||||
--------------------------
|
||||
All test suite options are now in one class called SimpleTestOptions.
|
||||
This means that options are set differently...
|
||||
|
||||
GroupTest::ignore() --> SimpleTestOptions::ignore()
|
||||
Mock::setMockBaseClass() --> SimpleTestOptions::setMockBaseClass()
|
||||
|
||||
These changed in Alpha8 and the old versions are now removed in RC1.
|
||||
|
||||
No method setExpected*()
|
||||
------------------------
|
||||
The mock expectations changed their names in Alpha4 and the old names
|
||||
ceased to be supported in Alpha8. The changes are...
|
||||
|
||||
setExpectedArguments() --> expectArguments()
|
||||
setExpectedArgumentsSequence() --> expectArgumentsAt()
|
||||
setExpectedCallCount() --> expectCallCount()
|
||||
setMaximumCallCount() --> expectMaximumCallCount()
|
||||
|
||||
The parameters remained the same.
|
@ -1,502 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
@ -1,102 +0,0 @@
|
||||
SimpleTest
|
||||
==========
|
||||
|
||||
You probably got this package from:
|
||||
|
||||
http://simpletest.org/en/download.html
|
||||
|
||||
If there is no licence agreement with this package please download
|
||||
a version from the location above. You must read and accept that
|
||||
licence to use this software. The file is titled simply LICENSE.
|
||||
|
||||
What is it? It's a framework for unit testing, web site testing and
|
||||
mock objects for PHP 5.0.5+.
|
||||
|
||||
If you have used JUnit, you will find this PHP unit testing version very
|
||||
similar. Also included is a mock objects and server stubs generator.
|
||||
The stubs can have return values set for different arguments, can have
|
||||
sequences set also by arguments and can return items by reference.
|
||||
The mocks inherit all of this functionality and can also have
|
||||
expectations set, again in sequences and for different arguments.
|
||||
|
||||
A web tester similar in concept to JWebUnit is also included. There is no
|
||||
JavaScript or tables support, but forms, authentication, cookies and
|
||||
frames are handled.
|
||||
|
||||
You can see a release schedule at http://simpletest.org/en/overview.html
|
||||
which is also copied to the documentation folder with this release.
|
||||
A full PHPDocumenter API documentation exists at
|
||||
http://simpletest.org/api/.
|
||||
|
||||
The user interface is minimal in the extreme, but a lot of information
|
||||
flows from the test suite. After version 1.0 we will release a better
|
||||
web UI, but we are leaving XUL and GTK versions to volunteers as
|
||||
everybody has their own opinion on a good GUI, and we don't want to
|
||||
discourage development by shipping one with the toolkit. You can
|
||||
download an Eclipse plug-in separately.
|
||||
|
||||
The unit tests for SimpleTest itself can be run here:
|
||||
|
||||
test/unit_tests.php
|
||||
|
||||
And tests involving live network connections as well are here:
|
||||
|
||||
test/all_tests.php
|
||||
|
||||
The full tests will typically overrun the 8Mb limit often allowed
|
||||
to a PHP process. A workaround is to run the tests on the command
|
||||
with a custom php.ini file or with the switch -dmemory_limit=-1
|
||||
if you do not have access to your server version.
|
||||
|
||||
The full tests read some test data from simpletest.org. If the site
|
||||
is down or has been modified for a later version then you will get
|
||||
spurious errors. A unit_tests.php failure on the other hand would be
|
||||
very serious. Please notify us if you find one.
|
||||
|
||||
Even if all of the tests run please verify that your existing test suites
|
||||
also function as expected. The file:
|
||||
|
||||
HELP_MY_TESTS_DONT_WORK_ANYMORE
|
||||
|
||||
...contains information on interface changes. It also points out
|
||||
deprecated interfaces, so you should read this even if all of
|
||||
your current tests appear to run.
|
||||
|
||||
There is a documentation folder which contains the core reference information
|
||||
in English and French, although this information is fairly basic.
|
||||
You can find a tutorial on...
|
||||
|
||||
http://simpletest.org/en/first_test_tutorial.html
|
||||
|
||||
...to get you started and this material will eventually become included
|
||||
with the project documentation. A French translation exists at:
|
||||
|
||||
http://simpletest.org/fr/first_test_tutorial.html
|
||||
|
||||
If you download and use, and possibly even extend this tool, please let us
|
||||
know. Any feedback, even bad, is always welcome and we will work to get
|
||||
your suggestions into the next release. Ideally please send your
|
||||
comments to:
|
||||
|
||||
simpletest-support@lists.sourceforge.net
|
||||
|
||||
...so that others can read them too. We usually try to respond within 48
|
||||
hours.
|
||||
|
||||
There is no change log except at Sourceforge. You can visit the
|
||||
release notes to see the completed TODO list after each cycle and also the
|
||||
status of any bugs, but if the bug is recent then it will be fixed in SVN only.
|
||||
The SVN check-ins always have all the tests passing and so SVN snapshots should
|
||||
be pretty usable, although the code may not look so good internally.
|
||||
|
||||
Oh, and one last thing: SimpleTest is called "Simple" because it should
|
||||
be simple to use. We intend to add a complete set of tools for a test
|
||||
first and "test as you code" type of development. "Simple" does not mean
|
||||
"Lite" in this context.
|
||||
|
||||
Thanks to everyone who has sent comments and offered suggestions. They
|
||||
really are invaluable, but sadly you are too many to mention in full.
|
||||
Thanks to all on the advanced PHP forum on SitePoint, especially Harry
|
||||
Fuecks. Early adopters are always an inspiration.
|
||||
|
||||
-- Marcus Baker, Jason Sweat, Travis Swicegood, Perrick Penet and Edward Z. Yang.
|
@ -1 +0,0 @@
|
||||
1.1.0
|
@ -1,224 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* base include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
* @version $Id: dumper.php 1909 2009-07-29 15:58:11Z dgheath $
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses the command line arguments.
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class SimpleArguments {
|
||||
private $all = array();
|
||||
|
||||
/**
|
||||
* Parses the command line arguments. The usual formats
|
||||
* are supported:
|
||||
* -f value
|
||||
* -f=value
|
||||
* --flag=value
|
||||
* --flag value
|
||||
* -f (true)
|
||||
* --flag (true)
|
||||
* @param array $arguments Normally the PHP $argv.
|
||||
*/
|
||||
function __construct($arguments) {
|
||||
array_shift($arguments);
|
||||
while (count($arguments) > 0) {
|
||||
list($key, $value) = $this->parseArgument($arguments);
|
||||
$this->assign($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value in the argments object. If multiple
|
||||
* values are added under the same key, the key will
|
||||
* give an array value in the order they were added.
|
||||
* @param string $key The variable to assign to.
|
||||
* @param string value The value that would norally
|
||||
* be colected on the command line.
|
||||
*/
|
||||
function assign($key, $value) {
|
||||
if ($this->$key === false) {
|
||||
$this->all[$key] = $value;
|
||||
} elseif (! is_array($this->$key)) {
|
||||
$this->all[$key] = array($this->$key, $value);
|
||||
} else {
|
||||
$this->all[$key][] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the next key and value from the argument list.
|
||||
* @param array $arguments The remaining arguments to be parsed.
|
||||
* The argument list will be reduced.
|
||||
* @return array Two item array of key and value.
|
||||
* If no value can be found it will
|
||||
* have the value true assigned instead.
|
||||
*/
|
||||
private function parseArgument(&$arguments) {
|
||||
$argument = array_shift($arguments);
|
||||
if (preg_match('/^-(\w)=(.+)$/', $argument, $matches)) {
|
||||
return array($matches[1], $matches[2]);
|
||||
} elseif (preg_match('/^-(\w)$/', $argument, $matches)) {
|
||||
return array($matches[1], $this->nextNonFlagElseTrue($arguments));
|
||||
} elseif (preg_match('/^--(\w+)=(.+)$/', $argument, $matches)) {
|
||||
return array($matches[1], $matches[2]);
|
||||
} elseif (preg_match('/^--(\w+)$/', $argument, $matches)) {
|
||||
return array($matches[1], $this->nextNonFlagElseTrue($arguments));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to use the next argument as a value. It
|
||||
* won't use what it thinks is a flag.
|
||||
* @param array $arguments Remaining arguments to be parsed.
|
||||
* This variable is modified if there
|
||||
* is a value to be extracted.
|
||||
* @return string/boolean The next value unless it's a flag.
|
||||
*/
|
||||
private function nextNonFlagElseTrue(&$arguments) {
|
||||
return $this->valueIsNext($arguments) ? array_shift($arguments) : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the next available argument is a valid value.
|
||||
* If it starts with "-" or "--" it's a flag and doesn't count.
|
||||
* @param array $arguments Remaining arguments to be parsed.
|
||||
* Not affected by this call.
|
||||
* boolean True if valid value.
|
||||
*/
|
||||
function valueIsNext($arguments) {
|
||||
return isset($arguments[0]) && ! $this->isFlag($arguments[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* It's a flag if it starts with "-" or "--".
|
||||
* @param string $argument Value to be tested.
|
||||
* @return boolean True if it's a flag.
|
||||
*/
|
||||
function isFlag($argument) {
|
||||
return strncmp($argument, '-', 1) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The arguments are available as individual member
|
||||
* variables on the object.
|
||||
* @param string $key Argument name.
|
||||
* @return string/array/boolean Either false for no value,
|
||||
* the value as a string or
|
||||
* a list of multiple values if
|
||||
* the flag had been specified more
|
||||
* than once.
|
||||
*/
|
||||
function __get($key) {
|
||||
if (isset($this->all[$key])) {
|
||||
return $this->all[$key];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The entire argument set as a hash.
|
||||
* @return hash Each argument and it's value(s).
|
||||
*/
|
||||
function all() {
|
||||
return $this->all;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the help for the command line arguments.
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class SimpleHelp {
|
||||
private $overview;
|
||||
private $flag_sets = array();
|
||||
private $explanations = array();
|
||||
|
||||
/**
|
||||
* Sets up the top level explanation for the program.
|
||||
* @param string $overview Summary of program.
|
||||
*/
|
||||
function __construct($overview = '') {
|
||||
$this->overview = $overview;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the explanation for a group of flags that all
|
||||
* have the same function.
|
||||
* @param string/array $flags Flag and alternates. Don't
|
||||
* worry about leading dashes
|
||||
* as these are inserted automatically.
|
||||
* @param string $explanation What that flag group does.
|
||||
*/
|
||||
function explainFlag($flags, $explanation) {
|
||||
$flags = is_array($flags) ? $flags : array($flags);
|
||||
$this->flag_sets[] = $flags;
|
||||
$this->explanations[] = $explanation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the help text.
|
||||
* @returns string The complete formatted text.
|
||||
*/
|
||||
function render() {
|
||||
$tab_stop = $this->longestFlag($this->flag_sets) + 4;
|
||||
$text = $this->overview . "\n";
|
||||
for ($i = 0; $i < count($this->flag_sets); $i++) {
|
||||
$text .= $this->renderFlagSet($this->flag_sets[$i], $this->explanations[$i], $tab_stop);
|
||||
}
|
||||
return $this->noDuplicateNewLines($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Works out the longest flag for formatting purposes.
|
||||
* @param array $flag_sets The internal flag set list.
|
||||
*/
|
||||
private function longestFlag($flag_sets) {
|
||||
$longest = 0;
|
||||
foreach ($flag_sets as $flags) {
|
||||
foreach ($flags as $flag) {
|
||||
$longest = max($longest, strlen($this->renderFlag($flag)));
|
||||
}
|
||||
}
|
||||
return $longest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the text for a single flag and it's alternate flags.
|
||||
* @returns string Help text for that flag group.
|
||||
*/
|
||||
private function renderFlagSet($flags, $explanation, $tab_stop) {
|
||||
$flag = array_shift($flags);
|
||||
$text = str_pad($this->renderFlag($flag), $tab_stop, ' ') . $explanation . "\n";
|
||||
foreach ($flags as $flag) {
|
||||
$text .= ' ' . $this->renderFlag($flag) . "\n";
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the flag name including leading dashes.
|
||||
* @param string $flag Just the name.
|
||||
* @returns Fag with apropriate dashes.
|
||||
*/
|
||||
private function renderFlag($flag) {
|
||||
return (strlen($flag) == 1 ? '-' : '--') . $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts multiple new lines into a single new line.
|
||||
* Just there to trap accidental duplicate new lines.
|
||||
* @param string $text Text to clean up.
|
||||
* @returns string Text with no blank lines.
|
||||
*/
|
||||
private function noDuplicateNewLines($text) {
|
||||
return preg_replace('/(\n+)/', "\n", $text);
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,237 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Base include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
* @version $Id: authentication.php 2011 2011-04-29 08:22:48Z pp11 $
|
||||
*/
|
||||
/**
|
||||
* include http class
|
||||
*/
|
||||
require_once(dirname(__FILE__) . '/http.php');
|
||||
|
||||
/**
|
||||
* Represents a single security realm's identity.
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
*/
|
||||
class SimpleRealm {
|
||||
private $type;
|
||||
private $root;
|
||||
private $username;
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* Starts with the initial entry directory.
|
||||
* @param string $type Authentication type for this
|
||||
* realm. Only Basic authentication
|
||||
* is currently supported.
|
||||
* @param SimpleUrl $url Somewhere in realm.
|
||||
* @access public
|
||||
*/
|
||||
function SimpleRealm($type, $url) {
|
||||
$this->type = $type;
|
||||
$this->root = $url->getBasePath();
|
||||
$this->username = false;
|
||||
$this->password = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another location to the realm.
|
||||
* @param SimpleUrl $url Somewhere in realm.
|
||||
* @access public
|
||||
*/
|
||||
function stretch($url) {
|
||||
$this->root = $this->getCommonPath($this->root, $url->getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the common starting path.
|
||||
* @param string $first Path to compare.
|
||||
* @param string $second Path to compare.
|
||||
* @return string Common directories.
|
||||
* @access private
|
||||
*/
|
||||
protected function getCommonPath($first, $second) {
|
||||
$first = explode('/', $first);
|
||||
$second = explode('/', $second);
|
||||
for ($i = 0; $i < min(count($first), count($second)); $i++) {
|
||||
if ($first[$i] != $second[$i]) {
|
||||
return implode('/', array_slice($first, 0, $i)) . '/';
|
||||
}
|
||||
}
|
||||
return implode('/', $first) . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identity to try within this realm.
|
||||
* @param string $username Username in authentication dialog.
|
||||
* @param string $username Password in authentication dialog.
|
||||
* @access public
|
||||
*/
|
||||
function setIdentity($username, $password) {
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for current identity.
|
||||
* @return string Last succesful username.
|
||||
* @access public
|
||||
*/
|
||||
function getUsername() {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for current identity.
|
||||
* @return string Last succesful password.
|
||||
* @access public
|
||||
*/
|
||||
function getPassword() {
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the URL is within the directory
|
||||
* tree of the realm.
|
||||
* @param SimpleUrl $url URL to test.
|
||||
* @return boolean True if subpath.
|
||||
* @access public
|
||||
*/
|
||||
function isWithin($url) {
|
||||
if ($this->isIn($this->root, $url->getBasePath())) {
|
||||
return true;
|
||||
}
|
||||
if ($this->isIn($this->root, $url->getBasePath() . $url->getPage() . '/')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if one string is a substring of
|
||||
* another.
|
||||
* @param string $part Small bit.
|
||||
* @param string $whole Big bit.
|
||||
* @return boolean True if the small bit is
|
||||
* in the big bit.
|
||||
* @access private
|
||||
*/
|
||||
protected function isIn($part, $whole) {
|
||||
return strpos($whole, $part) === 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages security realms.
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
*/
|
||||
class SimpleAuthenticator {
|
||||
private $realms;
|
||||
|
||||
/**
|
||||
* Clears the realms.
|
||||
* @access public
|
||||
*/
|
||||
function SimpleAuthenticator() {
|
||||
$this->restartSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts with no realms set up.
|
||||
* @access public
|
||||
*/
|
||||
function restartSession() {
|
||||
$this->realms = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new realm centered the current URL.
|
||||
* Browsers privatey wildly on their behaviour in this
|
||||
* regard. Mozilla ignores the realm and presents
|
||||
* only when challenged, wasting bandwidth. IE
|
||||
* just carries on presenting until a new challenge
|
||||
* occours. SimpleTest tries to follow the spirit of
|
||||
* the original standards committee and treats the
|
||||
* base URL as the root of a file tree shaped realm.
|
||||
* @param SimpleUrl $url Base of realm.
|
||||
* @param string $type Authentication type for this
|
||||
* realm. Only Basic authentication
|
||||
* is currently supported.
|
||||
* @param string $realm Name of realm.
|
||||
* @access public
|
||||
*/
|
||||
function addRealm($url, $type, $realm) {
|
||||
$this->realms[$url->getHost()][$realm] = new SimpleRealm($type, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current identity to be presented
|
||||
* against that realm.
|
||||
* @param string $host Server hosting realm.
|
||||
* @param string $realm Name of realm.
|
||||
* @param string $username Username for realm.
|
||||
* @param string $password Password for realm.
|
||||
* @access public
|
||||
*/
|
||||
function setIdentityForRealm($host, $realm, $username, $password) {
|
||||
if (isset($this->realms[$host][$realm])) {
|
||||
$this->realms[$host][$realm]->setIdentity($username, $password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the name of the realm by comparing URLs.
|
||||
* @param SimpleUrl $url URL to test.
|
||||
* @return SimpleRealm Name of realm.
|
||||
* @access private
|
||||
*/
|
||||
protected function findRealmFromUrl($url) {
|
||||
if (! isset($this->realms[$url->getHost()])) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->realms[$url->getHost()] as $name => $realm) {
|
||||
if ($realm->isWithin($url)) {
|
||||
return $realm;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the appropriate headers for this location.
|
||||
* @param SimpleHttpRequest $request Request to modify.
|
||||
* @param SimpleUrl $url Base of realm.
|
||||
* @access public
|
||||
*/
|
||||
function addHeaders(&$request, $url) {
|
||||
if ($url->getUsername() && $url->getPassword()) {
|
||||
$username = $url->getUsername();
|
||||
$password = $url->getPassword();
|
||||
} elseif ($realm = $this->findRealmFromUrl($url)) {
|
||||
$username = $realm->getUsername();
|
||||
$password = $realm->getPassword();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
$this->addBasicHeaders($request, $username, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents the appropriate headers for this
|
||||
* location for basic authentication.
|
||||
* @param SimpleHttpRequest $request Request to modify.
|
||||
* @param string $username Username for realm.
|
||||
* @param string $password Password for realm.
|
||||
* @access public
|
||||
*/
|
||||
static function addBasicHeaders(&$request, $username, $password) {
|
||||
if ($username && $password) {
|
||||
$request->addHeaderLine(
|
||||
'Authorization: Basic ' . base64_encode("$username:$password"));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,101 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Autorunner which runs all tests cases found in a file
|
||||
* that includes this module.
|
||||
* @package SimpleTest
|
||||
* @version $Id: autorun.php 2037 2011-11-30 17:58:21Z pp11 $
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* include simpletest files
|
||||
*/
|
||||
require_once dirname(__FILE__) . '/unit_tester.php';
|
||||
require_once dirname(__FILE__) . '/mock_objects.php';
|
||||
require_once dirname(__FILE__) . '/collector.php';
|
||||
require_once dirname(__FILE__) . '/default_reporter.php';
|
||||
/**#@-*/
|
||||
|
||||
$GLOBALS['SIMPLETEST_AUTORUNNER_INITIAL_CLASSES'] = get_declared_classes();
|
||||
$GLOBALS['SIMPLETEST_AUTORUNNER_INITIAL_PATH'] = getcwd();
|
||||
register_shutdown_function('simpletest_autorun');
|
||||
|
||||
/**
|
||||
* Exit handler to run all recent test cases and exit system if in CLI
|
||||
*/
|
||||
function simpletest_autorun() {
|
||||
chdir($GLOBALS['SIMPLETEST_AUTORUNNER_INITIAL_PATH']);
|
||||
if (tests_have_run()) {
|
||||
return;
|
||||
}
|
||||
$result = run_local_tests();
|
||||
if (SimpleReporter::inCli()) {
|
||||
exit($result ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* run all recent test cases if no test has
|
||||
* so far been run. Uses the DefaultReporter which can have
|
||||
* it's output controlled with SimpleTest::prefer().
|
||||
* @return boolean/null false if there were test failures, true if
|
||||
* there were no failures, null if tests are
|
||||
* already running
|
||||
*/
|
||||
function run_local_tests() {
|
||||
try {
|
||||
if (tests_have_run()) {
|
||||
return;
|
||||
}
|
||||
$candidates = capture_new_classes();
|
||||
$loader = new SimpleFileLoader();
|
||||
$suite = $loader->createSuiteFromClasses(
|
||||
basename(initial_file()),
|
||||
$loader->selectRunnableTests($candidates));
|
||||
return $suite->run(new DefaultReporter());
|
||||
} catch (Exception $stack_frame_fix) {
|
||||
print $stack_frame_fix->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current test context to see if a test has
|
||||
* ever been run.
|
||||
* @return boolean True if tests have run.
|
||||
*/
|
||||
function tests_have_run() {
|
||||
if ($context = SimpleTest::getContext()) {
|
||||
return (boolean)$context->getTest();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The first autorun file.
|
||||
* @return string Filename of first autorun script.
|
||||
*/
|
||||
function initial_file() {
|
||||
static $file = false;
|
||||
if (! $file) {
|
||||
if (isset($_SERVER, $_SERVER['SCRIPT_FILENAME'])) {
|
||||
$file = $_SERVER['SCRIPT_FILENAME'];
|
||||
} else {
|
||||
$included_files = get_included_files();
|
||||
$file = reset($included_files);
|
||||
}
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every class since the first autorun include. This
|
||||
* is safe enough if require_once() is always used.
|
||||
* @return array Class names.
|
||||
*/
|
||||
function capture_new_classes() {
|
||||
global $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES;
|
||||
return array_map('strtolower', array_diff(get_declared_classes(),
|
||||
$SIMPLETEST_AUTORUNNER_INITIAL_CLASSES ?
|
||||
$SIMPLETEST_AUTORUNNER_INITIAL_CLASSES : array()));
|
||||
}
|
||||
?>
|
File diff suppressed because it is too large
Load Diff
@ -1,122 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This file contains the following classes: {@link SimpleCollector},
|
||||
* {@link SimplePatternCollector}.
|
||||
*
|
||||
* @author Travis Swicegood <development@domain51.com>
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
* @version $Id: collector.php 2011 2011-04-29 08:22:48Z pp11 $
|
||||
*/
|
||||
|
||||
/**
|
||||
* The basic collector for {@link GroupTest}
|
||||
*
|
||||
* @see collect(), GroupTest::collect()
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class SimpleCollector {
|
||||
|
||||
/**
|
||||
* Strips off any kind of slash at the end so as to normalise the path.
|
||||
* @param string $path Path to normalise.
|
||||
* @return string Path without trailing slash.
|
||||
*/
|
||||
protected function removeTrailingSlash($path) {
|
||||
if (substr($path, -1) == DIRECTORY_SEPARATOR) {
|
||||
return substr($path, 0, -1);
|
||||
} elseif (substr($path, -1) == '/') {
|
||||
return substr($path, 0, -1);
|
||||
} else {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the directory and adds what it can.
|
||||
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
||||
* @param string $path Directory to scan.
|
||||
* @see _attemptToAdd()
|
||||
*/
|
||||
function collect(&$test, $path) {
|
||||
$path = $this->removeTrailingSlash($path);
|
||||
if ($handle = opendir($path)) {
|
||||
while (($entry = readdir($handle)) !== false) {
|
||||
if ($this->isHidden($entry)) {
|
||||
continue;
|
||||
}
|
||||
$this->handle($test, $path . DIRECTORY_SEPARATOR . $entry);
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method determines what should be done with a given file and adds
|
||||
* it via {@link GroupTest::addTestFile()} if necessary.
|
||||
*
|
||||
* This method should be overriden to provide custom matching criteria,
|
||||
* such as pattern matching, recursive matching, etc. For an example, see
|
||||
* {@link SimplePatternCollector::_handle()}.
|
||||
*
|
||||
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
||||
* @param string $filename A filename as generated by {@link collect()}
|
||||
* @see collect()
|
||||
* @access protected
|
||||
*/
|
||||
protected function handle(&$test, $file) {
|
||||
if (is_dir($file)) {
|
||||
return;
|
||||
}
|
||||
$test->addFile($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for hidden files so as to skip them. Currently
|
||||
* only tests for Unix hidden files.
|
||||
* @param string $filename Plain filename.
|
||||
* @return boolean True if hidden file.
|
||||
* @access private
|
||||
*/
|
||||
protected function isHidden($filename) {
|
||||
return strncmp($filename, '.', 1) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension to {@link SimpleCollector} that only adds files matching a
|
||||
* given pattern.
|
||||
*
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
* @see SimpleCollector
|
||||
*/
|
||||
class SimplePatternCollector extends SimpleCollector {
|
||||
private $pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $pattern Perl compatible regex to test name against
|
||||
* See {@link http://us4.php.net/manual/en/reference.pcre.pattern.syntax.php PHP's PCRE}
|
||||
* for full documentation of valid pattern.s
|
||||
*/
|
||||
function __construct($pattern = '/php$/i') {
|
||||
$this->pattern = $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to add files that match a given pattern.
|
||||
*
|
||||
* @see SimpleCollector::_handle()
|
||||
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
||||
* @param string $path Directory to scan.
|
||||
* @access protected
|
||||
*/
|
||||
protected function handle(&$test, $filename) {
|
||||
if (preg_match($this->pattern, $filename)) {
|
||||
parent::handle($test, $filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,166 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* base include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @version $Id: compatibility.php 1900 2009-07-29 11:44:37Z lastcraft $
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static methods for compatibility between different
|
||||
* PHP versions.
|
||||
* @package SimpleTest
|
||||
*/
|
||||
class SimpleTestCompatibility {
|
||||
|
||||
/**
|
||||
* Creates a copy whether in PHP5 or PHP4.
|
||||
* @param object $object Thing to copy.
|
||||
* @return object A copy.
|
||||
* @access public
|
||||
*/
|
||||
static function copy($object) {
|
||||
if (version_compare(phpversion(), '5') >= 0) {
|
||||
eval('$copy = clone $object;');
|
||||
return $copy;
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identity test. Drops back to equality + types for PHP5
|
||||
* objects as the === operator counts as the
|
||||
* stronger reference constraint.
|
||||
* @param mixed $first Test subject.
|
||||
* @param mixed $second Comparison object.
|
||||
* @return boolean True if identical.
|
||||
* @access public
|
||||
*/
|
||||
static function isIdentical($first, $second) {
|
||||
if (version_compare(phpversion(), '5') >= 0) {
|
||||
return SimpleTestCompatibility::isIdenticalType($first, $second);
|
||||
}
|
||||
if ($first != $second) {
|
||||
return false;
|
||||
}
|
||||
return ($first === $second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive type test.
|
||||
* @param mixed $first Test subject.
|
||||
* @param mixed $second Comparison object.
|
||||
* @return boolean True if same type.
|
||||
* @access private
|
||||
*/
|
||||
protected static function isIdenticalType($first, $second) {
|
||||
if (gettype($first) != gettype($second)) {
|
||||
return false;
|
||||
}
|
||||
if (is_object($first) && is_object($second)) {
|
||||
if (get_class($first) != get_class($second)) {
|
||||
return false;
|
||||
}
|
||||
return SimpleTestCompatibility::isArrayOfIdenticalTypes(
|
||||
(array) $first,
|
||||
(array) $second);
|
||||
}
|
||||
if (is_array($first) && is_array($second)) {
|
||||
return SimpleTestCompatibility::isArrayOfIdenticalTypes($first, $second);
|
||||
}
|
||||
if ($first !== $second) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive type test for each element of an array.
|
||||
* @param mixed $first Test subject.
|
||||
* @param mixed $second Comparison object.
|
||||
* @return boolean True if identical.
|
||||
* @access private
|
||||
*/
|
||||
protected static function isArrayOfIdenticalTypes($first, $second) {
|
||||
if (array_keys($first) != array_keys($second)) {
|
||||
return false;
|
||||
}
|
||||
foreach (array_keys($first) as $key) {
|
||||
$is_identical = SimpleTestCompatibility::isIdenticalType(
|
||||
$first[$key],
|
||||
$second[$key]);
|
||||
if (! $is_identical) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for two variables being aliases.
|
||||
* @param mixed $first Test subject.
|
||||
* @param mixed $second Comparison object.
|
||||
* @return boolean True if same.
|
||||
* @access public
|
||||
*/
|
||||
static function isReference(&$first, &$second) {
|
||||
if (version_compare(phpversion(), '5', '>=') && is_object($first)) {
|
||||
return ($first === $second);
|
||||
}
|
||||
if (is_object($first) && is_object($second)) {
|
||||
$id = uniqid("test");
|
||||
$first->$id = true;
|
||||
$is_ref = isset($second->$id);
|
||||
unset($first->$id);
|
||||
return $is_ref;
|
||||
}
|
||||
$temp = $first;
|
||||
$first = uniqid("test");
|
||||
$is_ref = ($first === $second);
|
||||
$first = $temp;
|
||||
return $is_ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if an object is a member of a
|
||||
* class hiearchy.
|
||||
* @param object $object Object to test.
|
||||
* @param string $class Root name of hiearchy.
|
||||
* @return boolean True if class in hiearchy.
|
||||
* @access public
|
||||
*/
|
||||
static function isA($object, $class) {
|
||||
if (version_compare(phpversion(), '5') >= 0) {
|
||||
if (! class_exists($class, false)) {
|
||||
if (function_exists('interface_exists')) {
|
||||
if (! interface_exists($class, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
eval("\$is_a = \$object instanceof $class;");
|
||||
return $is_a;
|
||||
}
|
||||
if (function_exists('is_a')) {
|
||||
return is_a($object, $class);
|
||||
}
|
||||
return ((strtolower($class) == get_class($object))
|
||||
or (is_subclass_of($object, $class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a socket timeout for each chunk.
|
||||
* @param resource $handle Socket handle.
|
||||
* @param integer $timeout Limit in seconds.
|
||||
* @access public
|
||||
*/
|
||||
static function setTimeout($handle, $timeout) {
|
||||
if (function_exists('stream_set_timeout')) {
|
||||
stream_set_timeout($handle, $timeout, 0);
|
||||
} elseif (function_exists('socket_set_timeout')) {
|
||||
socket_set_timeout($handle, $timeout, 0);
|
||||
} elseif (function_exists('set_socket_timeout')) {
|
||||
set_socket_timeout($handle, $timeout, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,380 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Base include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
* @version $Id: cookies.php 2011 2011-04-29 08:22:48Z pp11 $
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* include other SimpleTest class files
|
||||
*/
|
||||
require_once(dirname(__FILE__) . '/url.php');
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Cookie data holder. Cookie rules are full of pretty
|
||||
* arbitary stuff. I have used...
|
||||
* http://wp.netscape.com/newsref/std/cookie_spec.html
|
||||
* http://www.cookiecentral.com/faq/
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
*/
|
||||
class SimpleCookie {
|
||||
private $host;
|
||||
private $name;
|
||||
private $value;
|
||||
private $path;
|
||||
private $expiry;
|
||||
private $is_secure;
|
||||
|
||||
/**
|
||||
* Constructor. Sets the stored values.
|
||||
* @param string $name Cookie key.
|
||||
* @param string $value Value of cookie.
|
||||
* @param string $path Cookie path if not host wide.
|
||||
* @param string $expiry Expiry date as string.
|
||||
* @param boolean $is_secure Currently ignored.
|
||||
*/
|
||||
function __construct($name, $value = false, $path = false, $expiry = false, $is_secure = false) {
|
||||
$this->host = false;
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
$this->path = ($path ? $this->fixPath($path) : "/");
|
||||
$this->expiry = false;
|
||||
if (is_string($expiry)) {
|
||||
$this->expiry = strtotime($expiry);
|
||||
} elseif (is_integer($expiry)) {
|
||||
$this->expiry = $expiry;
|
||||
}
|
||||
$this->is_secure = $is_secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the host. The cookie rules determine
|
||||
* that the first two parts are taken for
|
||||
* certain TLDs and three for others. If the
|
||||
* new host does not match these rules then the
|
||||
* call will fail.
|
||||
* @param string $host New hostname.
|
||||
* @return boolean True if hostname is valid.
|
||||
* @access public
|
||||
*/
|
||||
function setHost($host) {
|
||||
if ($host = $this->truncateHost($host)) {
|
||||
$this->host = $host;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the truncated host to which this
|
||||
* cookie applies.
|
||||
* @return string Truncated hostname.
|
||||
* @access public
|
||||
*/
|
||||
function getHost() {
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for a cookie being valid for a host name.
|
||||
* @param string $host Host to test against.
|
||||
* @return boolean True if the cookie would be valid
|
||||
* here.
|
||||
*/
|
||||
function isValidHost($host) {
|
||||
return ($this->truncateHost($host) === $this->getHost());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts just the domain part that determines a
|
||||
* cookie's host validity.
|
||||
* @param string $host Host name to truncate.
|
||||
* @return string Domain or false on a bad host.
|
||||
* @access private
|
||||
*/
|
||||
protected function truncateHost($host) {
|
||||
$tlds = SimpleUrl::getAllTopLevelDomains();
|
||||
if (preg_match('/[a-z\-]+\.(' . $tlds . ')$/i', $host, $matches)) {
|
||||
return $matches[0];
|
||||
} elseif (preg_match('/[a-z\-]+\.[a-z\-]+\.[a-z\-]+$/i', $host, $matches)) {
|
||||
return $matches[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for name.
|
||||
* @return string Cookie key.
|
||||
* @access public
|
||||
*/
|
||||
function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for value. A deleted cookie will
|
||||
* have an empty string for this.
|
||||
* @return string Cookie value.
|
||||
* @access public
|
||||
*/
|
||||
function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for path.
|
||||
* @return string Valid cookie path.
|
||||
* @access public
|
||||
*/
|
||||
function getPath() {
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a path to see if the cookie applies
|
||||
* there. The test path must be longer or
|
||||
* equal to the cookie path.
|
||||
* @param string $path Path to test against.
|
||||
* @return boolean True if cookie valid here.
|
||||
* @access public
|
||||
*/
|
||||
function isValidPath($path) {
|
||||
return (strncmp(
|
||||
$this->fixPath($path),
|
||||
$this->getPath(),
|
||||
strlen($this->getPath())) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for expiry.
|
||||
* @return string Expiry string.
|
||||
* @access public
|
||||
*/
|
||||
function getExpiry() {
|
||||
if (! $this->expiry) {
|
||||
return false;
|
||||
}
|
||||
return gmdate("D, d M Y H:i:s", $this->expiry) . " GMT";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if cookie is expired against
|
||||
* the cookie format time or timestamp.
|
||||
* Will give true for a session cookie.
|
||||
* @param integer/string $now Time to test against. Result
|
||||
* will be false if this time
|
||||
* is later than the cookie expiry.
|
||||
* Can be either a timestamp integer
|
||||
* or a cookie format date.
|
||||
* @access public
|
||||
*/
|
||||
function isExpired($now) {
|
||||
if (! $this->expiry) {
|
||||
return true;
|
||||
}
|
||||
if (is_string($now)) {
|
||||
$now = strtotime($now);
|
||||
}
|
||||
return ($this->expiry < $now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ages the cookie by the specified number of
|
||||
* seconds.
|
||||
* @param integer $interval In seconds.
|
||||
* @public
|
||||
*/
|
||||
function agePrematurely($interval) {
|
||||
if ($this->expiry) {
|
||||
$this->expiry -= $interval;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the secure flag.
|
||||
* @return boolean True if cookie needs SSL.
|
||||
* @access public
|
||||
*/
|
||||
function isSecure() {
|
||||
return $this->is_secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a trailing and leading slash to the path
|
||||
* if missing.
|
||||
* @param string $path Path to fix.
|
||||
* @access private
|
||||
*/
|
||||
protected function fixPath($path) {
|
||||
if (substr($path, 0, 1) != '/') {
|
||||
$path = '/' . $path;
|
||||
}
|
||||
if (substr($path, -1, 1) != '/') {
|
||||
$path .= '/';
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository for cookies. This stuff is a
|
||||
* tiny bit browser dependent.
|
||||
* @package SimpleTest
|
||||
* @subpackage WebTester
|
||||
*/
|
||||
class SimpleCookieJar {
|
||||
private $cookies;
|
||||
|
||||
/**
|
||||
* Constructor. Jar starts empty.
|
||||
* @access public
|
||||
*/
|
||||
function __construct() {
|
||||
$this->cookies = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes expired and temporary cookies as if
|
||||
* the browser was closed and re-opened.
|
||||
* @param string/integer $now Time to test expiry against.
|
||||
* @access public
|
||||
*/
|
||||
function restartSession($date = false) {
|
||||
$surviving_cookies = array();
|
||||
for ($i = 0; $i < count($this->cookies); $i++) {
|
||||
if (! $this->cookies[$i]->getValue()) {
|
||||
continue;
|
||||
}
|
||||
if (! $this->cookies[$i]->getExpiry()) {
|
||||
continue;
|
||||
}
|
||||
if ($date && $this->cookies[$i]->isExpired($date)) {
|
||||
continue;
|
||||
}
|
||||
$surviving_cookies[] = $this->cookies[$i];
|
||||
}
|
||||
$this->cookies = $surviving_cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ages all cookies in the cookie jar.
|
||||
* @param integer $interval The old session is moved
|
||||
* into the past by this number
|
||||
* of seconds. Cookies now over
|
||||
* age will be removed.
|
||||
* @access public
|
||||
*/
|
||||
function agePrematurely($interval) {
|
||||
for ($i = 0; $i < count($this->cookies); $i++) {
|
||||
$this->cookies[$i]->agePrematurely($interval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an additional cookie. If a cookie has
|
||||
* the same name and path it is replaced.
|
||||
* @param string $name Cookie key.
|
||||
* @param string $value Value of cookie.
|
||||
* @param string $host Host upon which the cookie is valid.
|
||||
* @param string $path Cookie path if not host wide.
|
||||
* @param string $expiry Expiry date.
|
||||
* @access public
|
||||
*/
|
||||
function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
|
||||
$cookie = new SimpleCookie($name, $value, $path, $expiry);
|
||||
if ($host) {
|
||||
$cookie->setHost($host);
|
||||
}
|
||||
$this->cookies[$this->findFirstMatch($cookie)] = $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a matching cookie to write over or the
|
||||
* first empty slot if none.
|
||||
* @param SimpleCookie $cookie Cookie to write into jar.
|
||||
* @return integer Available slot.
|
||||
* @access private
|
||||
*/
|
||||
protected function findFirstMatch($cookie) {
|
||||
for ($i = 0; $i < count($this->cookies); $i++) {
|
||||
$is_match = $this->isMatch(
|
||||
$cookie,
|
||||
$this->cookies[$i]->getHost(),
|
||||
$this->cookies[$i]->getPath(),
|
||||
$this->cookies[$i]->getName());
|
||||
if ($is_match) {
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
return count($this->cookies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the most specific cookie value from the
|
||||
* browser cookies. Looks for the longest path that
|
||||
* matches.
|
||||
* @param string $host Host to search.
|
||||
* @param string $path Applicable path.
|
||||
* @param string $name Name of cookie to read.
|
||||
* @return string False if not present, else the
|
||||
* value as a string.
|
||||
* @access public
|
||||
*/
|
||||
function getCookieValue($host, $path, $name) {
|
||||
$longest_path = '';
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($this->isMatch($cookie, $host, $path, $name)) {
|
||||
if (strlen($cookie->getPath()) > strlen($longest_path)) {
|
||||
$value = $cookie->getValue();
|
||||
$longest_path = $cookie->getPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (isset($value) ? $value : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests cookie for matching against search
|
||||
* criteria.
|
||||
* @param SimpleTest $cookie Cookie to test.
|
||||
* @param string $host Host must match.
|
||||
* @param string $path Cookie path must be shorter than
|
||||
* this path.
|
||||
* @param string $name Name must match.
|
||||
* @return boolean True if matched.
|
||||
* @access private
|
||||
*/
|
||||
protected function isMatch($cookie, $host, $path, $name) {
|
||||
if ($cookie->getName() != $name) {
|
||||
return false;
|
||||
}
|
||||
if ($host && $cookie->getHost() && ! $cookie->isValidHost($host)) {
|
||||
return false;
|
||||
}
|
||||
if (! $cookie->isValidPath($path)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a URL to sift relevant cookies by host and
|
||||
* path. Results are list of strings of form "name=value".
|
||||
* @param SimpleUrl $url Url to select by.
|
||||
* @return array Valid name and value pairs.
|
||||
* @access public
|
||||
*/
|
||||
function selectAsPairs($url) {
|
||||
$pairs = array();
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($this->isMatch($cookie, $url->getHost(), $url->getPath(), $cookie->getName())) {
|
||||
$pairs[] = $cookie->getName() . '=' . $cookie->getValue();
|
||||
}
|
||||
}
|
||||
return $pairs;
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,163 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Optional include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
* @version $Id: default_reporter.php 2011 2011-04-29 08:22:48Z pp11 $
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* include other SimpleTest class files
|
||||
*/
|
||||
require_once(dirname(__FILE__) . '/simpletest.php');
|
||||
require_once(dirname(__FILE__) . '/scorer.php');
|
||||
require_once(dirname(__FILE__) . '/reporter.php');
|
||||
require_once(dirname(__FILE__) . '/xml.php');
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Parser for command line arguments. Extracts
|
||||
* the a specific test to run and engages XML
|
||||
* reporting when necessary.
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class SimpleCommandLineParser {
|
||||
private $to_property = array(
|
||||
'case' => 'case', 'c' => 'case',
|
||||
'test' => 'test', 't' => 'test',
|
||||
);
|
||||
private $case = '';
|
||||
private $test = '';
|
||||
private $xml = false;
|
||||
private $help = false;
|
||||
private $no_skips = false;
|
||||
|
||||
/**
|
||||
* Parses raw command line arguments into object properties.
|
||||
* @param string $arguments Raw commend line arguments.
|
||||
*/
|
||||
function __construct($arguments) {
|
||||
if (! is_array($arguments)) {
|
||||
return;
|
||||
}
|
||||
foreach ($arguments as $i => $argument) {
|
||||
if (preg_match('/^--?(test|case|t|c)=(.+)$/', $argument, $matches)) {
|
||||
$property = $this->to_property[$matches[1]];
|
||||
$this->$property = $matches[2];
|
||||
} elseif (preg_match('/^--?(test|case|t|c)$/', $argument, $matches)) {
|
||||
$property = $this->to_property[$matches[1]];
|
||||
if (isset($arguments[$i + 1])) {
|
||||
$this->$property = $arguments[$i + 1];
|
||||
}
|
||||
} elseif (preg_match('/^--?(xml|x)$/', $argument)) {
|
||||
$this->xml = true;
|
||||
} elseif (preg_match('/^--?(no-skip|no-skips|s)$/', $argument)) {
|
||||
$this->no_skips = true;
|
||||
} elseif (preg_match('/^--?(help|h)$/', $argument)) {
|
||||
$this->help = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run only this test.
|
||||
* @return string Test name to run.
|
||||
*/
|
||||
function getTest() {
|
||||
return $this->test;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run only this test suite.
|
||||
* @return string Test class name to run.
|
||||
*/
|
||||
function getTestCase() {
|
||||
return $this->case;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output should be XML or not.
|
||||
* @return boolean True if XML desired.
|
||||
*/
|
||||
function isXml() {
|
||||
return $this->xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output should suppress skip messages.
|
||||
* @return boolean True for no skips.
|
||||
*/
|
||||
function noSkips() {
|
||||
return $this->no_skips;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output should be a help message. Disabled during XML mode.
|
||||
* @return boolean True if help message desired.
|
||||
*/
|
||||
function help() {
|
||||
return $this->help && ! $this->xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns plain-text help message for command line runner.
|
||||
* @return string String help message
|
||||
*/
|
||||
function getHelpText() {
|
||||
return <<<HELP
|
||||
SimpleTest command line default reporter (autorun)
|
||||
Usage: php <test_file> [args...]
|
||||
|
||||
-c <class> Run only the test-case <class>
|
||||
-t <method> Run only the test method <method>
|
||||
-s Suppress skip messages
|
||||
-x Return test results in XML
|
||||
-h Display this help message
|
||||
|
||||
HELP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The default reporter used by SimpleTest's autorun
|
||||
* feature. The actual reporters used are dependency
|
||||
* injected and can be overridden.
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class DefaultReporter extends SimpleReporterDecorator {
|
||||
|
||||
/**
|
||||
* Assembles the appropriate reporter for the environment.
|
||||
*/
|
||||
function __construct() {
|
||||
if (SimpleReporter::inCli()) {
|
||||
$parser = new SimpleCommandLineParser($_SERVER['argv']);
|
||||
$interfaces = $parser->isXml() ? array('XmlReporter') : array('TextReporter');
|
||||
if ($parser->help()) {
|
||||
// I'm not sure if we should do the echo'ing here -- ezyang
|
||||
echo $parser->getHelpText();
|
||||
exit(1);
|
||||
}
|
||||
$reporter = new SelectiveReporter(
|
||||
SimpleTest::preferred($interfaces),
|
||||
$parser->getTestCase(),
|
||||
$parser->getTest());
|
||||
if ($parser->noSkips()) {
|
||||
$reporter = new NoSkipsReporter($reporter);
|
||||
}
|
||||
} else {
|
||||
$reporter = new SelectiveReporter(
|
||||
SimpleTest::preferred('HtmlReporter'),
|
||||
@$_GET['c'],
|
||||
@$_GET['t']);
|
||||
if (@$_GET['skips'] == 'no' || @$_GET['show-skips'] == 'no') {
|
||||
$reporter = new NoSkipsReporter($reporter);
|
||||
}
|
||||
}
|
||||
parent::__construct($reporter);
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,96 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* base include file for SimpleTest
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
* @version $Id: detached.php 1784 2008-04-26 13:07:14Z pp11 $
|
||||
*/
|
||||
|
||||
/**#@+
|
||||
* include other SimpleTest class files
|
||||
*/
|
||||
require_once(dirname(__FILE__) . '/xml.php');
|
||||
require_once(dirname(__FILE__) . '/shell_tester.php');
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Runs an XML formated test in a separate process.
|
||||
* @package SimpleTest
|
||||
* @subpackage UnitTester
|
||||
*/
|
||||
class DetachedTestCase {
|
||||
private $command;
|
||||
private $dry_command;
|
||||
private $size;
|
||||
|
||||
/**
|
||||
* Sets the location of the remote test.
|
||||
* @param string $command Test script.
|
||||
* @param string $dry_command Script for dry run.
|
||||
* @access public
|
||||
*/
|
||||
function __construct($command, $dry_command = false) {
|
||||
$this->command = $command;
|
||||
$this->dry_command = $dry_command ? $dry_command : $command;
|
||||
$this->size = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the test name for subclasses.
|
||||
* @return string Name of the test.
|
||||
* @access public
|
||||
*/
|
||||
function getLabel() {
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the top level test for this class. Currently
|
||||
* reads the data as a single chunk. I'll fix this
|
||||
* once I have added iteration to the browser.
|
||||
* @param SimpleReporter $reporter Target of test results.
|
||||
* @returns boolean True if no failures.
|
||||
* @access public
|
||||
*/
|
||||
function run(&$reporter) {
|
||||
$shell = &new SimpleShell();
|
||||
$shell->execute($this->command);
|
||||
$parser = &$this->createParser($reporter);
|
||||
if (! $parser->parse($shell->getOutput())) {
|
||||
trigger_error('Cannot parse incoming XML from [' . $this->command . ']');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the number of subtests.
|
||||
* @return integer Number of test cases.
|
||||
* @access public
|
||||
*/
|
||||
function getSize() {
|
||||
if ($this->size === false) {
|
||||
$shell = &new SimpleShell();
|
||||
$shell->execute($this->dry_command);
|
||||
$reporter = &new SimpleReporter();
|
||||
$parser = &$this->createParser($reporter);
|
||||
if (! $parser->parse($shell->getOutput())) {
|
||||
trigger_error('Cannot parse incoming XML from [' . $this->dry_command . ']');
|
||||
return false;
|
||||
}
|
||||
$this->size = $reporter->getTestCaseCount();
|
||||
}
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the XML parser.
|
||||
* @param SimpleReporter $reporter Target of test results.
|
||||
* @return SimpleTestXmlListener XML reader.
|
||||
* @access protected
|
||||
*/
|
||||
protected function &createParser(&$reporter) {
|
||||
return new SimpleTestXmlParser($reporter);
|
||||
}
|
||||
}
|
||||
?>
|
@ -1,378 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest documentation for testing log-in and authentication</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<span class="chosen">Authentication</span>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Authentication documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Getting through <a href="#basic">Basic HTTP authentication</a>
|
||||
</li>
|
||||
<li>
|
||||
Testing <a href="#cookies">cookie based authentication</a>
|
||||
</li>
|
||||
<li>
|
||||
Managing <a href="#session">browser sessions</a> and timeouts
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
|
||||
<p>
|
||||
One of the trickiest, and yet most important, areas
|
||||
of testing web sites is the security.
|
||||
Testing these schemes is one of the core goals of
|
||||
the SimpleTest web tester.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="basic"></a>Basic HTTP authentication</h2>
|
||||
<p>
|
||||
If you fetch a page protected by basic authentication then
|
||||
rather than receiving content, you will instead get a 401
|
||||
header.
|
||||
We can illustrate this with this test...
|
||||
<pre>
|
||||
class AuthenticationTest extends WebTestCase {<strong>
|
||||
function test401Header() {
|
||||
$this->get('http://www.lastcraft.com/protected/');
|
||||
$this->showHeaders();
|
||||
}</strong>
|
||||
}
|
||||
</pre>
|
||||
This allows us to see the challenge header...
|
||||
<div class="demo">
|
||||
<h1>File test</h1>
|
||||
<pre>
|
||||
HTTP/1.1 401 Authorization Required
|
||||
Date: Sat, 18 Sep 2004 19:25:18 GMT
|
||||
Server: Apache/1.3.29 (Unix) PHP/4.3.4
|
||||
WWW-Authenticate: Basic realm="SimpleTest basic authentication"
|
||||
Connection: close
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
</pre>
|
||||
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
||||
<strong>0</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
|
||||
</div>
|
||||
We are trying to get away from visual inspection though, and so SimpleTest
|
||||
allows to make automated assertions against the challenge.
|
||||
Here is a thorough test of our header...
|
||||
<pre>
|
||||
class AuthenticationTest extends WebTestCase {
|
||||
function test401Header() {
|
||||
$this->get('http://www.lastcraft.com/protected/');<strong>
|
||||
$this->assertAuthentication('Basic');
|
||||
$this->assertResponse(401);
|
||||
$this->assertRealm('SimpleTest basic authentication');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Any one of these tests would normally do on it's own depending
|
||||
on the amount of detail you want to see.
|
||||
</p>
|
||||
<p>
|
||||
One theme that runs through SimpleTest is the ability to use
|
||||
<span class="new_code">SimpleExpectation</span> objects wherever a simple
|
||||
match is not enough.
|
||||
If you want only an approximate match to the realm for
|
||||
example, you can do this...
|
||||
<pre>
|
||||
class AuthenticationTest extends WebTestCase {
|
||||
function test401Header() {
|
||||
$this->get('http://www.lastcraft.com/protected/');
|
||||
$this->assertRealm(<strong>new PatternExpectation('/simpletest/i')</strong>);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
This type of test, testing HTTP responses, is not typical.
|
||||
</p>
|
||||
<p>
|
||||
Most of the time we are not interested in testing the
|
||||
authentication itself, but want to get past it to test
|
||||
the pages underneath.
|
||||
As soon as the challenge has been issued we can reply with
|
||||
an authentication response...
|
||||
<pre>
|
||||
class AuthenticationTest extends WebTestCase {
|
||||
function testCanAuthenticate() {
|
||||
$this->get('http://www.lastcraft.com/protected/');<strong>
|
||||
$this->authenticate('Me', 'Secret');</strong>
|
||||
$this->assertTitle(...);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The username and password will now be sent with every
|
||||
subsequent request to that directory and subdirectories.
|
||||
You will have to authenticate again if you step outside
|
||||
the authenticated directory, but SimpleTest is smart enough
|
||||
to merge subdirectories into a common realm.
|
||||
</p>
|
||||
<p>
|
||||
If you want, you can shortcut this step further by encoding
|
||||
the log in details straight into the URL...
|
||||
<pre>
|
||||
class AuthenticationTest extends WebTestCase {
|
||||
function testCanReadAuthenticatedPages() {
|
||||
$this->get('http://<strong>Me:Secret@</strong>www.lastcraft.com/protected/');
|
||||
$this->assertTitle(...);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
If your username or password has special characters, then you
|
||||
will have to URL encode them or the request will not be parsed
|
||||
correctly.
|
||||
I'm afraid we leave this up to you.
|
||||
</p>
|
||||
<p>
|
||||
A problem with encoding the login details directly in the URL is
|
||||
the authentication header will not be sent on subsequent requests.
|
||||
If you navigate with relative URLs though, the authentication
|
||||
information will be preserved along with the domain name.
|
||||
</p>
|
||||
<p>
|
||||
Normally though, you use the <span class="new_code">authenticate()</span> call.
|
||||
SimpleTest will then remember your login information on each request.
|
||||
</p>
|
||||
<p>
|
||||
Only testing with basic authentication is currently supported, and
|
||||
this is only really secure in tandem with HTTPS connections.
|
||||
This is usually good enough to protect test server from prying eyes,
|
||||
however.
|
||||
Digest authentication and NTLM authentication may be added
|
||||
in the future if enough people request this feature.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="cookies"></a>Cookies</h2>
|
||||
<p>
|
||||
Basic authentication doesn't give enough control over the
|
||||
user interface for web developers.
|
||||
More likely this functionality will be coded directly into
|
||||
the web architecture using cookies with complicated timeouts.
|
||||
We need to be able to test this too.
|
||||
</p>
|
||||
<p>
|
||||
Starting with a simple log-in form...
|
||||
<pre>
|
||||
<form>
|
||||
Username:
|
||||
<input type="text" name="u" value="" /><br />
|
||||
Password:
|
||||
<input type="password" name="p" value="" /><br />
|
||||
<input type="submit" value="Log in" />
|
||||
</form>
|
||||
</pre>
|
||||
Which looks like...
|
||||
</p>
|
||||
<p>
|
||||
<form class="demo">
|
||||
Username:
|
||||
<input type="text" name="u" value=""><br>
|
||||
Password:
|
||||
<input type="password" name="p" value=""><br>
|
||||
<input type="submit" value="Log in">
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
Let's suppose that in fetching this page a cookie has been
|
||||
set with a session ID.
|
||||
We are not going to fill the form in yet, just test that
|
||||
we are tracking the user.
|
||||
Here is the test...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
function testSessionCookieSetBeforeForm() {
|
||||
$this->get('http://www.my-site.com/login.php');<strong>
|
||||
$this->assertCookie('SID');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
All we are doing is confirming that the cookie is set.
|
||||
As the value is likely to be rather cryptic it's not
|
||||
really worth testing this with...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
function testSessionCookieIsCorrectPattern() {
|
||||
$this->get('http://www.my-site.com/login.php');
|
||||
$this->assertCookie('SID', <strong>new PatternExpectation('/[a-f0-9]{32}/i')</strong>);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
If you are using PHP to handle sessions for you then
|
||||
this test is even more useless, as we are just testing PHP itself.
|
||||
</p>
|
||||
<p>
|
||||
The simplest test of logging in is to visually inspect the
|
||||
next page to see if you are really logged in.
|
||||
Just test the next page with <span class="new_code">WebTestCase::assertText()</span>.
|
||||
</p>
|
||||
<p>
|
||||
The test is similar to any other form test,
|
||||
but we might want to confirm that we still have the same
|
||||
cookie after log-in as before we entered.
|
||||
We wouldn't want to lose track of this after all.
|
||||
Here is a possible test for this...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
...
|
||||
function testSessionCookieSameAfterLogIn() {
|
||||
$this->get('http://www.my-site.com/login.php');<strong>
|
||||
$session = $this->getCookie('SID');
|
||||
$this->setField('u', 'Me');
|
||||
$this->setField('p', 'Secret');
|
||||
$this->click('Log in');
|
||||
$this->assertText('Welcome Me');
|
||||
$this->assertCookie('SID', $session);</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
This confirms that the session identifier is maintained
|
||||
afer log-in and we haven't accidently reset it.
|
||||
</p>
|
||||
<p>
|
||||
We could even attempt to hack our own system by setting
|
||||
arbitrary cookies to gain access...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
...
|
||||
function testSessionCookieSameAfterLogIn() {
|
||||
$this->get('http://www.my-site.com/login.php');<strong>
|
||||
$this->setCookie('SID', 'Some other session');
|
||||
$this->get('http://www.my-site.com/restricted.php');</strong>
|
||||
$this->assertText('Access denied');
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Is your site protected from this attack?
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="session"></a>Browser sessions</h2>
|
||||
<p>
|
||||
If you are testing an authentication system a critical piece
|
||||
of behaviour is what happens when a user logs back in.
|
||||
We would like to simulate closing and reopening a browser...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
...
|
||||
function testLoseAuthenticationAfterBrowserClose() {
|
||||
$this->get('http://www.my-site.com/login.php');
|
||||
$this->setField('u', 'Me');
|
||||
$this->setField('p', 'Secret');
|
||||
$this->click('Log in');
|
||||
$this->assertText('Welcome Me');<strong>
|
||||
|
||||
$this->restart();
|
||||
$this->get('http://www.my-site.com/restricted.php');
|
||||
$this->assertText('Access denied');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The <span class="new_code">WebTestCase::restart()</span> method will
|
||||
preserve cookies that have unexpired timeouts, but throw away
|
||||
those that are temporary or expired.
|
||||
You can optionally specify the time and date that the restart
|
||||
happened.
|
||||
</p>
|
||||
<p>
|
||||
Expiring cookies can be a problem.
|
||||
After all, if you have a cookie that expires after an hour,
|
||||
you don't want to stall the test for an hour while waiting
|
||||
for the cookie to pass it's timeout.
|
||||
</p>
|
||||
<p>
|
||||
To push the cookies over the hour limit you can age them
|
||||
before you restart the session...
|
||||
<pre>
|
||||
class LogInTest extends WebTestCase {
|
||||
...
|
||||
function testLoseAuthenticationAfterOneHour() {
|
||||
$this->get('http://www.my-site.com/login.php');
|
||||
$this->setField('u', 'Me');
|
||||
$this->setField('p', 'Secret');
|
||||
$this->click('Log in');
|
||||
$this->assertText('Welcome Me');
|
||||
<strong>
|
||||
$this->ageCookies(3600);</strong>
|
||||
$this->restart();
|
||||
$this->get('http://www.my-site.com/restricted.php');
|
||||
$this->assertText('Access denied');
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
After the restart it will appear that cookies are an
|
||||
hour older, and any that pass their expiry will have
|
||||
disappeared.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
<li>
|
||||
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
||||
gives full detail on the classes and assertions available.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<span class="chosen">Authentication</span>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,501 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest documentation for the scriptable web browser component</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<span class="chosen">Scriptable browser</span>
|
||||
</div></div>
|
||||
<h1>PHP Scriptable Web Browser</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Using the bundled <a href="#scripting">web browser in scripts</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#debug">Debugging</a> failed pages
|
||||
</li>
|
||||
<li>
|
||||
Complex <a href="#unit">tests with multiple web browsers</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
|
||||
<p>
|
||||
SimpleTest's web browser component can be used not just
|
||||
outside of the <span class="new_code">WebTestCase</span> class, but also
|
||||
independently of the SimpleTest framework itself.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="scripting"></a>The Scriptable Browser</h2>
|
||||
<p>
|
||||
You can use the web browser in PHP scripts to confirm
|
||||
services are up and running, or to extract information
|
||||
from them at a regular basis.
|
||||
For example, here is a small script to extract the current number of
|
||||
open PHP 5 bugs from the <a href="http://www.php.net/">PHP web site</a>...
|
||||
<pre>
|
||||
<strong><?php
|
||||
require_once('simpletest/browser.php');
|
||||
|
||||
$browser = &new SimpleBrowser();
|
||||
$browser->get('http://php.net/');
|
||||
$browser->click('reporting bugs');
|
||||
$browser->click('statistics');
|
||||
$page = $browser->click('PHP 5 bugs only');
|
||||
preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches);
|
||||
print $matches[1];
|
||||
?></strong>
|
||||
</pre>
|
||||
There are simpler methods to do this particular example in PHP
|
||||
of course.
|
||||
For example you can just use the PHP <span class="new_code">file()</span>
|
||||
command against what here is a pretty fixed page.
|
||||
However, using the web browser for scripts allows authentication,
|
||||
correct handling of cookies, automatic loading of frames, redirects,
|
||||
form submission and the ability to examine the page headers.
|
||||
<p>
|
||||
</p>
|
||||
Methods such as periodic scraping are fragile against a site that is constantly
|
||||
evolving and you would want a more direct way of accessing
|
||||
data in a permanent set up, but for simple tasks this can provide
|
||||
a very rapid solution.
|
||||
</p>
|
||||
<p>
|
||||
All of the navigation methods used in the
|
||||
<a href="web_tester_documentation.html">WebTestCase</a>
|
||||
are present in the <span class="new_code">SimpleBrowser</span> class, but
|
||||
the assertions are replaced with simpler accessors.
|
||||
Here is a full list of the page navigation methods...
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">addHeader($header)</span></td>
|
||||
<td>Adds a header to every fetch</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">useProxy($proxy, $username, $password)</span></td>
|
||||
<td>Use this proxy from now on</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">head($url, $parameters)</span></td>
|
||||
<td>Perform a HEAD request</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">get($url, $parameters)</span></td>
|
||||
<td>Fetch a page with GET</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">post($url, $parameters)</span></td>
|
||||
<td>Fetch a page with POST</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">click($label)</span></td>
|
||||
<td>Clicks visible link or button text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickLink($label)</span></td>
|
||||
<td>Follows a link by label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickLinkById($id)</span></td>
|
||||
<td>Follows a link by attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getUrl()</span></td>
|
||||
<td>Current URL of page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getTitle()</span></td>
|
||||
<td>Page title</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getContent()</span></td>
|
||||
<td>Raw page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getContentAsText()</span></td>
|
||||
<td>HTML removed except for alt text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">retry()</span></td>
|
||||
<td>Repeat the last request</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">back()</span></td>
|
||||
<td>Use the browser back button</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">forward()</span></td>
|
||||
<td>Use the browser forward button</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">authenticate($username, $password)</span></td>
|
||||
<td>Retry page or frame after a 401 response</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">restart($date)</span></td>
|
||||
<td>Restarts the browser for a new session</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">ageCookies($interval)</span></td>
|
||||
<td>Ages the cookies by the specified time</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setCookie($name, $value)</span></td>
|
||||
<td>Sets an additional cookie</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getCookieValue($host, $path, $name)</span></td>
|
||||
<td>Reads the most specific cookie</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getCurrentCookieValue($name)</span></td>
|
||||
<td>Reads cookie for the current context</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
The methods <span class="new_code">SimpleBrowser::useProxy()</span> and
|
||||
<span class="new_code">SimpleBrowser::addHeader()</span> are special.
|
||||
Once called they continue to apply to all subsequent fetches.
|
||||
</p>
|
||||
<p>
|
||||
Navigating forms is similar to the
|
||||
<a href="form_testing_documentation.html">WebTestCase form navigation</a>...
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">setField($label, $value)</span></td>
|
||||
<td>Sets all form fields with that label or name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setFieldByName($name, $value)</span></td>
|
||||
<td>Sets all form fields with that name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setFieldById($id, $value)</span></td>
|
||||
<td>Sets all form fields with that id</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getField($label)</span></td>
|
||||
<td>Accessor for a form element value by label tag and then name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getFieldByName($name)</span></td>
|
||||
<td>Accessor for a form element value using name attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getFieldById($id)</span></td>
|
||||
<td>Accessor for a form element value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickSubmit($label)</span></td>
|
||||
<td>Submits form by button label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickSubmitByName($name)</span></td>
|
||||
<td>Submits form by button attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickSubmitById($id)</span></td>
|
||||
<td>Submits form by button attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickImage($label, $x, $y)</span></td>
|
||||
<td>Clicks an input tag of type image by title or alt text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickImageByName($name, $x, $y)</span></td>
|
||||
<td>Clicks an input tag of type image by name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clickImageById($id, $x, $y)</span></td>
|
||||
<td>Clicks an input tag of type image by ID attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">submitFormById($id)</span></td>
|
||||
<td>Submits by the form tag attribute</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
At the moment there aren't many methods to list available links and fields.
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">isClickable($label)</span></td>
|
||||
<td>Test to see if a click target exists by label or name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">isSubmit($label)</span></td>
|
||||
<td>Test for the existence of a button with that label or name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">isImage($label)</span></td>
|
||||
<td>Test for the existence of an image button with that label or name</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getLink($label)</span></td>
|
||||
<td>Finds a URL from its label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getLinkById($label)</span></td>
|
||||
<td>Finds a URL from its ID attribute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getUrls()</span></td>
|
||||
<td>Lists available links in the current page</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
This will be expanded in later versions of SimpleTest.
|
||||
</p>
|
||||
<p>
|
||||
Frames are a rather esoteric feature these days, but SimpleTest has
|
||||
retained support for them.
|
||||
</p>
|
||||
<p>
|
||||
Within a page, individual frames can be selected.
|
||||
If no selection is made then all the frames are merged together
|
||||
in one large conceptual page.
|
||||
The content of the current page will be a concatenation of all of the
|
||||
frames in the order that they were specified in the "frameset"
|
||||
tags.
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">getFrames()</span></td>
|
||||
<td>A dump of the current frame structure</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getFrameFocus()</span></td>
|
||||
<td>Current frame label or index</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setFrameFocusByIndex($choice)</span></td>
|
||||
<td>Select a frame numbered from 1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setFrameFocus($name)</span></td>
|
||||
<td>Select frame by label</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">clearFrameFocus()</span></td>
|
||||
<td>Treat all the frames as a single page</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
When focused on a single frame, the content will come from
|
||||
that frame only.
|
||||
This includes links to click and forms to submit.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="debug"></a>What went wrong?</h2>
|
||||
<p>
|
||||
All of this functionality is great when we actually manage to fetch pages,
|
||||
but that doesn't always happen.
|
||||
To help figure out what went wrong, the browser has some methods to
|
||||
aid in debugging...
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">setConnectionTimeout($timeout)</span></td>
|
||||
<td>Close the socket on overrun</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getUrl()</span></td>
|
||||
<td>Url of most recent page fetched</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getRequest()</span></td>
|
||||
<td>Raw request header of page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getHeaders()</span></td>
|
||||
<td>Raw response header of page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getTransportError()</span></td>
|
||||
<td>Any socket level errors in the last fetch</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getResponseCode()</span></td>
|
||||
<td>HTTP response of page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getMimeType()</span></td>
|
||||
<td>Mime type of page or frame</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getAuthentication()</span></td>
|
||||
<td>Authentication type in 401 challenge header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getRealm()</span></td>
|
||||
<td>Authentication realm in 401 challenge header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">getBaseUrl()</span></td>
|
||||
<td>Base url only of most recent page fetched</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setMaximumRedirects($max)</span></td>
|
||||
<td>Number of redirects before page is loaded anyway</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">setMaximumNestedFrames($max)</span></td>
|
||||
<td>Protection against recursive framesets</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">ignoreFrames()</span></td>
|
||||
<td>Disables frames support</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">useFrames()</span></td>
|
||||
<td>Enables frames support</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">ignoreCookies()</span></td>
|
||||
<td>Disables sending and receiving of cookies</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">useCookies()</span></td>
|
||||
<td>Enables cookie support</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
The methods <span class="new_code">SimpleBrowser::setConnectionTimeout()</span>
|
||||
<span class="new_code">SimpleBrowser::setMaximumRedirects()</span>,
|
||||
<span class="new_code">SimpleBrowser::setMaximumNestedFrames()</span>,
|
||||
<span class="new_code">SimpleBrowser::ignoreFrames()</span>,
|
||||
<span class="new_code">SimpleBrowser::useFrames()</span>,
|
||||
<span class="new_code">SimpleBrowser::ignoreCookies()</span> and
|
||||
<span class="new_code">SimpleBrowser::useCokies()</span> continue to apply
|
||||
to every subsequent request.
|
||||
The other methods are frames aware.
|
||||
This means that if you have an individual frame that is not
|
||||
loading, navigate to it using <span class="new_code">SimpleBrowser::setFrameFocus()</span>
|
||||
and you can then use <span class="new_code">SimpleBrowser::getRequest()</span>, etc to
|
||||
see what happened.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="unit"></a>Complex unit tests with multiple browsers</h2>
|
||||
<p>
|
||||
Anything that could be done in a
|
||||
<a href="web_tester_documentation.html">WebTestCase</a> can
|
||||
now be done in a <a href="unit_tester_documentation.html">UnitTestCase</a>.
|
||||
This means that we could freely mix domain object testing with the
|
||||
web interface...
|
||||
<pre>
|
||||
<strong>class TestOfRegistration extends UnitTestCase {
|
||||
function testNewUserAddedToAuthenticator() {</strong>
|
||||
$browser = new SimpleBrowser();
|
||||
$browser->get('http://my-site.com/register.php');
|
||||
$browser->setField('email', 'me@here');
|
||||
$browser->setField('password', 'Secret');
|
||||
$browser->click('Register');
|
||||
<strong>
|
||||
$authenticator = new Authenticator();
|
||||
$member = $authenticator->findByEmail('me@here');
|
||||
$this->assertEqual($member->getPassword(), 'Secret');
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
While this may be a useful temporary expediency, I am not a fan
|
||||
of this type of testing.
|
||||
The testing has cut across application layers, make it twice as
|
||||
likely it will need refactoring when the code changes.
|
||||
</p>
|
||||
<p>
|
||||
A more useful case of where using the browser directly can be helpful
|
||||
is where the <span class="new_code">WebTestCase</span> cannot cope.
|
||||
An example is where two browsers are needed at the same time.
|
||||
</p>
|
||||
<p>
|
||||
For example, say we want to disallow multiple simultaneous
|
||||
usage of a site with the same username.
|
||||
This test case will do the job...
|
||||
<pre>
|
||||
class TestOfSecurity extends UnitTestCase {
|
||||
function testNoMultipleLoginsFromSameUser() {<strong>
|
||||
$first_attempt = new SimpleBrowser();
|
||||
$first_attempt->get('http://my-site.com/login.php');
|
||||
$first_attempt->setField('name', 'Me');
|
||||
$first_attempt->setField('password', 'Secret');
|
||||
$first_attempt->click('Enter');
|
||||
$this->assertEqual($first_attempt->getTitle(), 'Welcome');
|
||||
|
||||
$second_attempt = new SimpleBrowser();
|
||||
$second_attempt->get('http://my-site.com/login.php');
|
||||
$second_attempt->setField('name', 'Me');
|
||||
$second_attempt->setField('password', 'Secret');
|
||||
$second_attempt->click('Enter');
|
||||
$this->assertEqual($second_attempt->getTitle(), 'Access Denied');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
You can also use the <span class="new_code">SimpleBrowser</span> class
|
||||
directly when you want to write test cases using a different
|
||||
test tool than SimpleTest, such as PHPUnit.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
<li>
|
||||
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
||||
gives full detail on the classes and assertions available.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<span class="chosen">Scriptable browser</span>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,121 +0,0 @@
|
||||
body {
|
||||
padding-left: 3%;
|
||||
padding-right: 3%;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
pre {
|
||||
font-family: "courier new", courier, typewriter, monospace;
|
||||
font-size: 90%;
|
||||
border: 1px solid;
|
||||
border-color: #999966;
|
||||
background-color: #ffffcc;
|
||||
padding: 5px;
|
||||
margin-left: 20px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
.code, .new_code, pre.new_code {
|
||||
font-family: "courier new", courier, typewriter, monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
div.copyright {
|
||||
font-size: 80%;
|
||||
color: gray;
|
||||
}
|
||||
div.copyright a {
|
||||
margin-top: 1em;
|
||||
color: gray;
|
||||
}
|
||||
ul.api {
|
||||
border: 2px outset;
|
||||
border-color: gray;
|
||||
background-color: white;
|
||||
margin: 5px;
|
||||
margin-left: 5%;
|
||||
margin-right: 5%;
|
||||
}
|
||||
ul.api li {
|
||||
margin-top: 0.2em;
|
||||
margin-bottom: 0.2em;
|
||||
list-style: none;
|
||||
text-indent: -3em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
div.demo {
|
||||
border: 4px ridge;
|
||||
border-color: gray;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
margin-left: 20px;
|
||||
margin-right: 40px;
|
||||
background-color: white;
|
||||
}
|
||||
div.demo span.fail {
|
||||
color: red;
|
||||
}
|
||||
div.demo span.pass {
|
||||
color: green;
|
||||
}
|
||||
div.demo h1 {
|
||||
font-size: 12pt;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
div.menu {
|
||||
text-align: center;
|
||||
}
|
||||
table {
|
||||
border: 2px outset;
|
||||
border-color: gray;
|
||||
background-color: white;
|
||||
margin: 5px;
|
||||
margin-left: 5%;
|
||||
margin-right: 5%;
|
||||
}
|
||||
td {
|
||||
font-size: 90%;
|
||||
}
|
||||
.shell {
|
||||
color: white;
|
||||
}
|
||||
pre.shell {
|
||||
border: 4px ridge;
|
||||
border-color: gray;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
margin-left: 20px;
|
||||
margin-right: 40px;
|
||||
background-color: #000100;
|
||||
color: #99ff99;
|
||||
font-size: 90%;
|
||||
}
|
||||
pre.file {
|
||||
color: black;
|
||||
border: 1px solid;
|
||||
border-color: black;
|
||||
padding: 10px;
|
||||
margin: 5px;
|
||||
margin-left: 20px;
|
||||
margin-right: 40px;
|
||||
background-color: white;
|
||||
font-size: 90%;
|
||||
}
|
||||
form.demo {
|
||||
background-color: lightgray;
|
||||
border: 4px outset;
|
||||
border-color: lightgray;
|
||||
padding: 10px;
|
||||
margin-right: 40%;
|
||||
}
|
||||
dl, dd {
|
||||
margin: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
em {
|
||||
font-weight: bold;
|
||||
font-family: "courier new", courier, typewriter, monospace;
|
||||
}
|
@ -1,476 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>
|
||||
Extending the SimpleTest unit tester with additional expectation classes
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<span class="chosen">Expectations</span>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Expectation documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Using expectations for
|
||||
<a href="#mock">more precise testing with mock objects</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#behaviour">Changing mock object behaviour</a> with expectations
|
||||
</li>
|
||||
<li>
|
||||
<a href="#extending">Extending the expectations</a>
|
||||
</li>
|
||||
<li>
|
||||
Underneath SimpleTest <a href="#unit">uses expectation classes</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<a class="target" name="mock"></a>More control over mock objects</h2>
|
||||
<p>
|
||||
The default behaviour of the
|
||||
<a href="mock_objects_documentation.html">mock objects</a>
|
||||
in
|
||||
<a href="http://sourceforge.net/projects/simpletest/">SimpleTest</a>
|
||||
is either an identical match on the argument or to allow any argument at all.
|
||||
For almost all tests this is sufficient.
|
||||
Sometimes, though, you want to weaken a test case.
|
||||
</p>
|
||||
<p>
|
||||
One place where a test can be too tightly coupled is with
|
||||
text matching.
|
||||
Suppose we have a component that outputs a helpful error
|
||||
message when something goes wrong.
|
||||
You want to test that the correct error was sent, but the actual
|
||||
text may be rather long.
|
||||
If you test for the text exactly, then every time the exact wording
|
||||
of the message changes, you will have to go back and edit the test suite.
|
||||
</p>
|
||||
<p>
|
||||
For example, suppose we have a news service that has failed
|
||||
to connect to its remote source.
|
||||
<pre>
|
||||
<strong>class NewsService {
|
||||
...
|
||||
function publish($writer) {
|
||||
if (! $this->isConnected()) {
|
||||
$writer->write('Cannot connect to news service "' .
|
||||
$this->_name . '" at this time. ' .
|
||||
'Please try again later.');
|
||||
}
|
||||
...
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
Here it is sending its content to a
|
||||
<span class="new_code">Writer</span> class.
|
||||
We could test this behaviour with a
|
||||
<span class="new_code">MockWriter</span> like so...
|
||||
<pre>
|
||||
class TestOfNewsService extends UnitTestCase {
|
||||
...
|
||||
function testConnectionFailure() {<strong>
|
||||
$writer = new MockWriter();
|
||||
$writer->expectOnce('write', array(
|
||||
'Cannot connect to news service ' .
|
||||
'"BBC News" at this time. ' .
|
||||
'Please try again later.'));
|
||||
|
||||
$service = new NewsService('BBC News');
|
||||
$service->publish($writer);</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
This is a good example of a brittle test.
|
||||
If we decide to add additional instructions, such as
|
||||
suggesting an alternative news source, we will break
|
||||
our tests even though no underlying functionality
|
||||
has been altered.
|
||||
</p>
|
||||
<p>
|
||||
To get around this, we would like to do a regular expression
|
||||
test rather than an exact match.
|
||||
We can actually do this with...
|
||||
<pre>
|
||||
class TestOfNewsService extends UnitTestCase {
|
||||
...
|
||||
function testConnectionFailure() {
|
||||
$writer = new MockWriter();<strong>
|
||||
$writer->expectOnce(
|
||||
'write',
|
||||
array(new PatternExpectation('/cannot connect/i')));</strong>
|
||||
|
||||
$service = new NewsService('BBC News');
|
||||
$service->publish($writer);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Instead of passing in the expected parameter to the
|
||||
<span class="new_code">MockWriter</span> we pass an
|
||||
expectation class called
|
||||
<span class="new_code">PatternExpectation</span>.
|
||||
The mock object is smart enough to recognise this as special
|
||||
and to treat it differently.
|
||||
Rather than simply comparing the incoming argument to this
|
||||
object, it uses the expectation object itself to
|
||||
perform the test.
|
||||
</p>
|
||||
<p>
|
||||
The <span class="new_code">PatternExpectation</span> takes
|
||||
the regular expression to match in its constructor.
|
||||
Whenever a comparison is made by the <span class="new_code">MockWriter</span>
|
||||
against this expectation class, it will do a
|
||||
<span class="new_code">preg_match()</span> with this pattern.
|
||||
With our test case above, as long as "cannot connect"
|
||||
appears in the text of the string, the mock will issue a pass
|
||||
to the unit tester.
|
||||
The rest of the text does not matter.
|
||||
</p>
|
||||
<p>
|
||||
The possible expectation classes are...
|
||||
<table><tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">AnythingExpectation</span></td>
|
||||
<td>Will always match</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">EqualExpectation</span></td>
|
||||
<td>An equality, rather than the stronger identity comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">NotEqualExpectation</span></td>
|
||||
<td>An inequality comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">IndenticalExpectation</span></td>
|
||||
<td>The default mock object check which must match exactly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">NotIndenticalExpectation</span></td>
|
||||
<td>Inverts the mock object logic</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">WithinMarginExpectation</span></td>
|
||||
<td>Compares a value to within a margin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">OutsideMarginExpectation</span></td>
|
||||
<td>Checks that a value is out side the margin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">PatternExpectation</span></td>
|
||||
<td>Uses a Perl Regex to match a string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">NoPatternExpectation</span></td>
|
||||
<td>Passes only if failing a Perl Regex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">IsAExpectation</span></td>
|
||||
<td>Checks the type or class name only</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">NotAExpectation</span></td>
|
||||
<td>Opposite of the <span class="new_code">IsAExpectation</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">MethodExistsExpectation</span></td>
|
||||
<td>Checks a method is available on an object</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">TrueExpectation</span></td>
|
||||
<td>Accepts any PHP variable that evaluates to true</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">FalseExpectation</span></td>
|
||||
<td>Accepts any PHP variable that evaluates to false</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
Most take the expected value in the constructor.
|
||||
The exceptions are the pattern matchers, which take a regular expression,
|
||||
and the <span class="new_code">IsAExpectation</span> and <span class="new_code">NotAExpectation</span> which takes a type
|
||||
or class name as a string.
|
||||
</p>
|
||||
<p>
|
||||
Some examples...
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
$mock->expectOnce('method', array(new IdenticalExpectation(14)));
|
||||
</pre>
|
||||
This is the same as <span class="new_code">$mock->expectOnce('method', array(14))</span>.
|
||||
<pre>
|
||||
$mock->expectOnce('method', array(new EqualExpectation(14)));
|
||||
</pre>
|
||||
This is different from the previous version in that the string
|
||||
<span class="new_code">"14"</span> as a parameter will also pass.
|
||||
Sometimes the additional type checks of SimpleTest are too restrictive.
|
||||
<pre>
|
||||
$mock->expectOnce('method', array(new AnythingExpectation(14)));
|
||||
</pre>
|
||||
This is the same as <span class="new_code">$mock->expectOnce('method', array('*'))</span>.
|
||||
<pre>
|
||||
$mock->expectOnce('method', array(new IdenticalExpectation('*')));
|
||||
</pre>
|
||||
This is handy if you want to assert a literal <span class="new_code">"*"</span>.
|
||||
<pre>
|
||||
new NotIdenticalExpectation(14)
|
||||
</pre>
|
||||
This matches on anything other than integer 14.
|
||||
Even the string <span class="new_code">"14"</span> would pass.
|
||||
<pre>
|
||||
new WithinMarginExpectation(14.0, 0.001)
|
||||
</pre>
|
||||
This will accept any value from 13.999 to 14.001 inclusive.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="behaviour"></a>Using expectations to control stubs</h2>
|
||||
<p>
|
||||
The expectation classes can be used not just for sending assertions
|
||||
from mock objects, but also for selecting behaviour for the
|
||||
<a href="mock_objects_documentation.html">mock objects</a>.
|
||||
Anywhere a list of arguments is given, a list of expectation objects
|
||||
can be inserted instead.
|
||||
</p>
|
||||
<p>
|
||||
Suppose we want a mock authorisation server to simulate a successful login,
|
||||
but only if it receives a valid session object.
|
||||
We can do this as follows...
|
||||
<pre>
|
||||
Mock::generate('Authorisation');
|
||||
<strong>
|
||||
$authorisation = new MockAuthorisation();
|
||||
$authorisation->returns(
|
||||
'isAllowed',
|
||||
true,
|
||||
array(new IsAExpectation('Session', 'Must be a session')));
|
||||
$authorisation->returns('isAllowed', false);</strong>
|
||||
</pre>
|
||||
We have set the default mock behaviour to return false when
|
||||
<span class="new_code">isAllowed</span> is called.
|
||||
When we call the method with a single parameter that
|
||||
is a <span class="new_code">Session</span> object, it will return true.
|
||||
We have also added a second parameter as a message.
|
||||
This will be displayed as part of the mock object
|
||||
failure message if this expectation is the cause of
|
||||
a failure.
|
||||
</p>
|
||||
<p>
|
||||
This kind of sophistication is rarely useful, but is included for
|
||||
completeness.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="extending"></a>Creating your own expectations</h2>
|
||||
<p>
|
||||
The expectation classes have a very simple structure.
|
||||
So simple that it is easy to create your own versions for
|
||||
commonly used test logic.
|
||||
</p>
|
||||
<p>
|
||||
As an example here is the creation of a class to test for
|
||||
valid IP addresses.
|
||||
In order to work correctly with the stubs and mocks the new
|
||||
expectation class should extend
|
||||
<span class="new_code">SimpleExpectation</span> or further extend a subclass...
|
||||
<pre>
|
||||
<strong>class ValidIp extends SimpleExpectation {
|
||||
|
||||
function test($ip) {
|
||||
return (ip2long($ip) != -1);
|
||||
}
|
||||
|
||||
function testMessage($ip) {
|
||||
return "Address [$ip] should be a valid IP address";
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
There are only two methods to implement.
|
||||
The <span class="new_code">test()</span> method should
|
||||
evaluate to true if the expectation is to pass, and
|
||||
false otherwise.
|
||||
The <span class="new_code">testMessage()</span> method
|
||||
should simply return some helpful text explaining the test
|
||||
that was carried out.
|
||||
</p>
|
||||
<p>
|
||||
This class can now be used in place of the earlier expectation
|
||||
classes.
|
||||
</p>
|
||||
<p>
|
||||
Here is a more typical example, matching part of a hash...
|
||||
<pre>
|
||||
<strong>class JustField extends EqualExpectation {
|
||||
private $key;
|
||||
|
||||
function __construct($key, $expected) {
|
||||
parent::__construct($expected);
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
function test($compare) {
|
||||
if (! isset($compare[$this->key])) {
|
||||
return false;
|
||||
}
|
||||
return parent::test($compare[$this->key]);
|
||||
}
|
||||
|
||||
function testMessage($compare) {
|
||||
if (! isset($compare[$this->key])) {
|
||||
return 'Key [' . $this->key . '] does not exist';
|
||||
}
|
||||
return 'Key [' . $this->key . '] -> ' .
|
||||
parent::testMessage($compare[$this->key]);
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
We tend to seperate message clauses with
|
||||
"&nbsp;->&nbsp;".
|
||||
This allows derivative tools to reformat the output.
|
||||
</p>
|
||||
<p>
|
||||
Suppose some authenticator is expecting to be given
|
||||
a database row corresponding to the user, and we
|
||||
only need to confirm the username is correct.
|
||||
We can assert just their username with...
|
||||
<pre>
|
||||
$mock->expectOnce('authenticate',
|
||||
array(new JustKey('username', 'marcus')));
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="unit"></a>Under the bonnet of the unit tester</h2>
|
||||
<p>
|
||||
The <a href="http://sourceforge.net/projects/simpletest/">SimpleTest unit testing framework</a>
|
||||
also uses the expectation classes internally for the
|
||||
<a href="unit_test_documentation.html">UnitTestCase class</a>.
|
||||
We can also take advantage of these mechanisms to reuse our
|
||||
homebrew expectation classes within the test suites directly.
|
||||
</p>
|
||||
<p>
|
||||
The most crude way of doing this is to use the generic
|
||||
<span class="new_code">SimpleTest::assert()</span> method to
|
||||
test against it directly...
|
||||
<pre>
|
||||
<strong>class TestOfNetworking extends UnitTestCase {
|
||||
...
|
||||
function testGetValidIp() {
|
||||
$server = &new Server();
|
||||
$this->assert(
|
||||
new ValidIp(),
|
||||
$server->getIp(),
|
||||
'Server IP address->%s');
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
<span class="new_code">assert()</span> will test any expectation class directly.
|
||||
</p>
|
||||
<p>
|
||||
This is a little untidy compared with our usual
|
||||
<span class="new_code">assert...()</span> syntax.
|
||||
</p>
|
||||
<p>
|
||||
For such a simple case we would normally create a
|
||||
separate assertion method on our test case rather
|
||||
than bother using the expectation class.
|
||||
If we pretend that our expectation is a little more
|
||||
complicated for a moment, so that we want to reuse it,
|
||||
we get...
|
||||
<pre>
|
||||
class TestOfNetworking extends UnitTestCase {
|
||||
...<strong>
|
||||
function assertValidIp($ip, $message = '%s') {
|
||||
$this->assert(new ValidIp(), $ip, $message);
|
||||
}</strong>
|
||||
|
||||
function testGetValidIp() {
|
||||
$server = &new Server();<strong>
|
||||
$this->assertValidIp(
|
||||
$server->getIp(),
|
||||
'Server IP address->%s');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
It is rare to need the expectations for more than pattern
|
||||
matching, but these facilities do allow testers to build
|
||||
some sort of domain language for testing their application.
|
||||
Also, complex expectation classes could make the tests
|
||||
harder to read and debug.
|
||||
In effect extending the test framework to create their own tool set.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
<li>
|
||||
The expectations mimic the constraints in <a href="http://www.jmock.org/">JMock</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://simpletest.org/api/">Full API for SimpleTest</a>
|
||||
from the PHPDoc.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<span class="chosen">Expectations</span>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,351 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest documentation for testing HTML forms</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<span class="chosen">Testing forms</span>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Form testing documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Changing form values and successfully
|
||||
<a href="#submit">Submitting a simple form</a>
|
||||
</li>
|
||||
<li>
|
||||
Handling <a href="#multiple">widgets with multiple values</a>
|
||||
by setting lists.
|
||||
</li>
|
||||
<li>
|
||||
Bypassing javascript to <a href="#hidden-field">set a hidden field</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#raw">Raw posting</a> when you don't have a button
|
||||
to click.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<a class="target" name="submit"></a>Submitting a simple form</h2>
|
||||
<p>
|
||||
When a page is fetched by the <span class="new_code">WebTestCase</span>
|
||||
using <span class="new_code">get()</span> or
|
||||
<span class="new_code">post()</span> the page content is
|
||||
automatically parsed.
|
||||
This results in any form controls that are inside <form> tags
|
||||
being available from within the test case.
|
||||
For example, if we have this snippet of HTML...
|
||||
<pre>
|
||||
<form>
|
||||
<input type="text" name="a" value="A default" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</pre>
|
||||
Which looks like this...
|
||||
</p>
|
||||
<p>
|
||||
<form class="demo">
|
||||
<input type="text" name="a" value="A default">
|
||||
<input type="submit" value="Go">
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
We can navigate to this code, via the
|
||||
<a href="http://www.lastcraft.com/form_testing_documentation.php">LastCraft</a>
|
||||
site, with the following test...
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {<strong>
|
||||
function testDefaultValue() {
|
||||
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
||||
$this->assertField('a', 'A default');
|
||||
}</strong>
|
||||
}
|
||||
</pre>
|
||||
Immediately after loading the page all of the HTML controls are set at
|
||||
their default values just as they would appear in the web browser.
|
||||
The assertion tests that a HTML widget exists in the page with the
|
||||
name "a" and that it is currently set to the value
|
||||
"A default".
|
||||
As usual, we could use a pattern expectation instead of a fixed
|
||||
string.
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
function testDefaultValue() {
|
||||
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
||||
$this->assertField('a', <strong>new PatternExpectation('/default/')</strong>);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
We could submit the form straight away, but first we'll change
|
||||
the value of the text field and only then submit it...
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
function testDefaultValue() {
|
||||
$this->get('http://www.my-site.com/');
|
||||
$this->assertField('a', 'A default');<strong>
|
||||
$this->setField('a', 'New value');
|
||||
$this->click('Go');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Because we didn't specify a method attribute on the form tag, and
|
||||
didn't specify an action either, the test case will follow
|
||||
the usual browser behaviour of submitting the form data as a <em>GET</em>
|
||||
request back to the same location.
|
||||
In general SimpleTest tries to emulate typical browser behaviour as much as possible,
|
||||
rather than attempting to catch any form of HTML omission.
|
||||
This is because the target of the testing framework is the PHP application
|
||||
logic, not syntax or other errors in the HTML code.
|
||||
For HTML errors, other tools such as
|
||||
<a href="http://www.w3.org/People/Raggett/tidy/">HTMLTidy</a> should be used,
|
||||
or any of the HTML and CSS validators already out there.
|
||||
</p>
|
||||
<p>
|
||||
If a field is not present in any form, or if an option is unavailable,
|
||||
then <span class="new_code">WebTestCase::setField()</span> will return
|
||||
<span class="new_code">false</span>.
|
||||
For example, suppose we wish to verify that a "Superuser"
|
||||
option is not present in this form...
|
||||
<pre>
|
||||
<strong>Select type of user to add:</strong>
|
||||
<select name="type">
|
||||
<option>Subscriber</option>
|
||||
<option>Author</option>
|
||||
<option>Administrator</option>
|
||||
</select>
|
||||
</pre>
|
||||
Which looks like...
|
||||
</p>
|
||||
<p>
|
||||
<form class="demo">
|
||||
<strong>Select type of user to add:</strong>
|
||||
<select name="type">
|
||||
<option>Subscriber</option>
|
||||
<option>Author</option>
|
||||
<option>Administrator</option>
|
||||
</select>
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
The following test will confirm it...
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
...
|
||||
function testNoSuperuserChoiceAvailable() {<strong>
|
||||
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
||||
$this->assertFalse($this->setField('type', 'Superuser'));</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The current selection will not be changed if the new value is not an option.
|
||||
</p>
|
||||
<p>
|
||||
Here is the full list of widgets currently supported...
|
||||
<ul>
|
||||
<li>Text fields, including hidden and password fields.</li>
|
||||
<li>Submit buttons including the button tag, although not yet reset buttons</li>
|
||||
<li>Text area. This includes text wrapping behaviour.</li>
|
||||
<li>Checkboxes, including multiple checkboxes in the same form.</li>
|
||||
<li>Drop down selections, including multiple selects.</li>
|
||||
<li>Radio buttons.</li>
|
||||
<li>Images.</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
The browser emulation offered by SimpleTest mimics
|
||||
the actions which can be perform by a user on a
|
||||
standard HTML page. Javascript is not supported, and
|
||||
it's unlikely that support will be added any time
|
||||
soon.
|
||||
</p>
|
||||
<p>
|
||||
Of particular note is that the Javascript idiom of
|
||||
passing form results by setting a hidden field cannot
|
||||
be performed using the normal SimpleTest
|
||||
commands. See below for a way to test such forms.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="multiple"></a>Fields with multiple values</h2>
|
||||
<p>
|
||||
SimpleTest can cope with two types of multivalue controls: Multiple
|
||||
selection drop downs, and multiple checkboxes with the same name
|
||||
within a form.
|
||||
The multivalue nature of these means that setting and testing
|
||||
are slightly different.
|
||||
Using checkboxes as an example...
|
||||
<pre>
|
||||
<form class="demo">
|
||||
<strong>Create privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="c" checked><br>
|
||||
<strong>Retrieve privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="r" checked><br>
|
||||
<strong>Update privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="u" checked><br>
|
||||
<strong>Destroy privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="d" checked><br>
|
||||
<input type="submit" value="Enable Privileges">
|
||||
</form>
|
||||
</pre>
|
||||
Which renders as...
|
||||
</p>
|
||||
<p>
|
||||
<form class="demo">
|
||||
<strong>Create privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="c" checked><br>
|
||||
<strong>Retrieve privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="r" checked><br>
|
||||
<strong>Update privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="u" checked><br>
|
||||
<strong>Destroy privileges allowed:</strong>
|
||||
<input type="checkbox" name="crud" value="d" checked><br>
|
||||
<input type="submit" value="Enable Privileges">
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
If we wish to disable all but the retrieval privileges and
|
||||
submit this information we can do it like this...
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
...<strong>
|
||||
function testDisableNastyPrivileges() {
|
||||
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
||||
$this->assertField('crud', array('c', 'r', 'u', 'd'));
|
||||
$this->setField('crud', array('r'));
|
||||
$this->click('Enable Privileges');
|
||||
}</strong>
|
||||
}
|
||||
</pre>
|
||||
Instead of setting the field to a single value, we give it a list
|
||||
of values.
|
||||
We do the same when testing expected values.
|
||||
We can then write other test code to confirm the effect of this, perhaps
|
||||
by logging in as that user and attempting an update.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="hidden-field"></a>Forms which use javascript to set a hidden field</h2>
|
||||
<p>
|
||||
If you want to test a form which relies on javascript to set a hidden
|
||||
field, you can't just call setField().
|
||||
The following code will <em>not</em> work:
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
function testEmulateMyJavascriptForm() {
|
||||
<strong>// This does *not* work</strong>
|
||||
$this->setField('a_hidden_field', '123');
|
||||
$this->clickSubmit('OK');
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Instead, you need to pass the additional form parameters to the
|
||||
clickSubmit() method:
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
function testMyJavascriptForm() {
|
||||
<strong>$this->clickSubmit('OK', array('a_hidden_field'=>'123'));</strong>
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
Bear in mind that in doing this you're effectively stubbing out a
|
||||
part of your software (the javascript code in the form), and
|
||||
perhaps you might be better off using something like
|
||||
<a href="http://selenium.openqa.org/">Selenium</a> to ensure a complete
|
||||
test.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="raw"></a>Raw posting</h2>
|
||||
<p>
|
||||
If you want to test a form handler, but have not yet written
|
||||
or do not have access to the form itself, you can create a
|
||||
form submission by hand.
|
||||
<pre>
|
||||
class SimpleFormTests extends WebTestCase {
|
||||
...<strong>
|
||||
function testAttemptedHack() {
|
||||
$this->post(
|
||||
'http://www.my-site.com/add_user.php',
|
||||
array('type' => 'superuser'));
|
||||
$this->assertNoText('user created');
|
||||
}</strong>
|
||||
}
|
||||
</pre>
|
||||
By adding data to the <span class="new_code">WebTestCase::post()</span>
|
||||
method, we are emulating a form submission.
|
||||
You would normally only do this as a temporary expedient, or where
|
||||
you are expecting a 3rd party to submit to a form.
|
||||
The exception is when you want tests to protect you from
|
||||
attempts to spoof your pages.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
<li>
|
||||
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
||||
gives full detail on the classes and assertions available.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<span class="chosen">Testing forms</span>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,252 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest for PHP test suites</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<span class="chosen">Group tests</span>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Test suite documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Different ways to <a href="#group">group tests</a> together.
|
||||
</li>
|
||||
<li>
|
||||
Combining group tests into <a href="#higher">larger groups</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<a class="target" name="group"></a>Grouping tests into suites</h2>
|
||||
<p>
|
||||
There are many ways to group tests together into test suites.
|
||||
One way is to simply place multiple test cases into a single file...
|
||||
<pre>
|
||||
<strong><?php
|
||||
require_once(dirname(__FILE__) . '/simpletest/autorun.php');
|
||||
require_once(dirname(__FILE__) . '/../classes/io.php');
|
||||
|
||||
class FileTester extends UnitTestCase {
|
||||
...
|
||||
}
|
||||
|
||||
class SocketTester extends UnitTestCase {
|
||||
...
|
||||
}
|
||||
?></strong>
|
||||
</pre>
|
||||
As many cases as needed can appear in a single file.
|
||||
They should include any code they need, such as the library
|
||||
being tested, but need none of the SimpleTest libraries.
|
||||
</p>
|
||||
<p>
|
||||
Occasionally special subclasses are created that methods useful
|
||||
for testing part of the application.
|
||||
These new base classes are then used in place of <span class="new_code">UnitTestCase</span>
|
||||
or <span class="new_code">WebTestCase</span>.
|
||||
You don't normally want to run these as test cases.
|
||||
Simply mark any base test cases that should not be run as abstract...
|
||||
<pre>
|
||||
<strong>abstract</strong> class MyFileTestCase extends UnitTestCase {
|
||||
...
|
||||
}
|
||||
|
||||
class FileTester extends MyFileTestCase { ... }
|
||||
|
||||
class SocketTester extends UnitTestCase { ... }
|
||||
</pre>
|
||||
Here the <span class="new_code">FileTester</span> class does
|
||||
not contain any actual tests, but is the base class for other
|
||||
test cases.
|
||||
</p>
|
||||
<p>
|
||||
We will call this sample <em>file_test.php</em>.
|
||||
Currently the test cases are grouped simply by being in the same file.
|
||||
We can build larger constructs just by including other test files in.
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('file_test.php');
|
||||
?>
|
||||
</pre>
|
||||
This will work, but create a purely flat hierarchy.
|
||||
INstead we create a test suite file.
|
||||
Our top level test suite can look like this...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
class AllFileTests extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
<strong>$this->addFile('file_test.php');</strong>
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
What happens here is that the <span class="new_code">TestSuite</span>
|
||||
class will do the <span class="new_code">require_once()</span>
|
||||
for us.
|
||||
It then checks to see if any new test case classes
|
||||
have been created by the new file and automatically composes
|
||||
them to the test suite.
|
||||
This method gives us the most control as we just manually add
|
||||
more test files as our test suite grows.
|
||||
</p>
|
||||
<p>
|
||||
If this is too much typing, and you are willing to group
|
||||
test suites together in their own directories or otherwise
|
||||
tag the file names, then there is a more automatic way...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
class AllFileTests extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->collect(dirname(__FILE__) . '/unit',
|
||||
new SimplePatternCollector('/_test.php/'));
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
This will scan a directory called "unit" for any files
|
||||
ending with "_test.php" and load them.
|
||||
You don't have to use <span class="new_code">SimplePatternCollector</span> to
|
||||
filter by a pattern in the filename, but this is the most common
|
||||
usage.
|
||||
</p>
|
||||
<p>
|
||||
That snippet above is very common in practice.
|
||||
Now all you have to do is drop a file of test cases into the
|
||||
directory and it will run just by running the test suite script.
|
||||
</p>
|
||||
<p>
|
||||
The catch is that you cannot control the order in which the test
|
||||
cases are run.
|
||||
If you want to see lower level components fail first in the test suite,
|
||||
and this will make diagnosis a lot easier, then you should manually
|
||||
call <span class="new_code">addFile()</span> for these.
|
||||
Tests cases are only loaded once, so it's fine to have these included
|
||||
again by a directory scan.
|
||||
</p>
|
||||
<p>
|
||||
Test cases loaded with the <span class="new_code">addFile</span> method have some
|
||||
useful properties.
|
||||
You can guarantee that the constructor is run
|
||||
just before the first test method and the destructor
|
||||
is run just after the last test method.
|
||||
This allows you to place test case wide set up and tear down
|
||||
code in the constructor and destructor, just like a normal
|
||||
class.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="higher"></a>Composite suites</h2>
|
||||
<p>
|
||||
The above method places all of the test cases into one large suite.
|
||||
For larger projects though this may not be flexible enough; you
|
||||
may want to group the tests together in all sorts of ways.
|
||||
</p>
|
||||
<p>
|
||||
Everything we have described so far with test scripts applies to
|
||||
<span class="new_code">TestSuite</span>s as well...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
<strong>
|
||||
class BigTestSuite extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addFile('file_tests.php');
|
||||
}
|
||||
}</strong>
|
||||
?>
|
||||
</pre>
|
||||
This effectively adds our test cases and a single suite below
|
||||
the first.
|
||||
When a test fails, we see the breadcrumb trail of the nesting.
|
||||
We can even mix groups and test cases freely as long as
|
||||
we are careful about loops in our includes.
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
class BigTestSuite extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addFile('file_tests.php');
|
||||
<strong>$this->addFile('some_other_test.php');</strong>
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
Note that in the event of a double include, ony the first instance
|
||||
of the test case will be run.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<span class="chosen">Group tests</span>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,870 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest for PHP mock objects documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<span class="chosen">Mock objects</span>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Mock objects documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#what">What are mock objects?</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#creation">Creating mock objects</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#expectations">Mocks as critics</a> with expectations.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<a class="target" name="what"></a>What are mock objects?</h2>
|
||||
<p>
|
||||
Mock objects have two roles during a test case: actor and critic.
|
||||
</p>
|
||||
<p>
|
||||
The actor behaviour is to simulate objects that are difficult to
|
||||
set up or time consuming to set up for a test.
|
||||
The classic example is a database connection.
|
||||
Setting up a test database at the start of each test would slow
|
||||
testing to a crawl and would require the installation of the
|
||||
database engine and test data on the test machine.
|
||||
If we can simulate the connection and return data of our
|
||||
choosing we not only win on the pragmatics of testing, but can
|
||||
also feed our code spurious data to see how it responds.
|
||||
We can simulate databases being down or other extremes
|
||||
without having to create a broken database for real.
|
||||
In other words, we get greater control of the test environment.
|
||||
</p>
|
||||
<p>
|
||||
If mock objects only behaved as actors they would simply be
|
||||
known as "server stubs".
|
||||
This was originally a pattern named by Robert Binder (<a href="">Testing
|
||||
object-oriented systems</a>: models, patterns, and tools,
|
||||
Addison-Wesley) in 1999.
|
||||
</p>
|
||||
<p>
|
||||
A server stub is a simulation of an object or component.
|
||||
It should exactly replace a component in a system for test
|
||||
or prototyping purposes, but remain lightweight.
|
||||
This allows tests to run more quickly, or if the simulated
|
||||
class has not been written, to run at all.
|
||||
</p>
|
||||
<p>
|
||||
However, the mock objects not only play a part (by supplying chosen
|
||||
return values on demand) they are also sensitive to the
|
||||
messages sent to them (via expectations).
|
||||
By setting expected parameters for a method call they act
|
||||
as a guard that the calls upon them are made correctly.
|
||||
If expectations are not met they save us the effort of
|
||||
writing a failed test assertion by performing that duty on our
|
||||
behalf.
|
||||
</p>
|
||||
<p>
|
||||
In the case of an imaginary database connection they can
|
||||
test that the query, say SQL, was correctly formed by
|
||||
the object that is using the connection.
|
||||
Set them up with fairly tight expectations and you will
|
||||
hardly need manual assertions at all.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="creation"></a>Creating mock objects</h2>
|
||||
<p>
|
||||
All we need is an existing class or interface, say a database connection
|
||||
that looks like this...
|
||||
<pre>
|
||||
<strong>class DatabaseConnection {
|
||||
function DatabaseConnection() { }
|
||||
function query($sql) { }
|
||||
function selectQuery($sql) { }
|
||||
}</strong>
|
||||
</pre>
|
||||
To create a mock version of the class we need to run a
|
||||
code generator...
|
||||
<pre>
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('database_connection.php');
|
||||
|
||||
<strong>Mock::generate('DatabaseConnection');</strong>
|
||||
</pre>
|
||||
This code generates a clone class called
|
||||
<span class="new_code">MockDatabaseConnection</span>.
|
||||
This new class appears to be the same, but actually has no behaviour at all.
|
||||
</p>
|
||||
<p>
|
||||
The new class is usually a subclass of <span class="new_code">DatabaseConnection</span>.
|
||||
Unfortunately, there is no way to create a mock version of a
|
||||
class with a <span class="new_code">final</span> method without having a living version of
|
||||
that method.
|
||||
We consider that unsafe.
|
||||
If the target is an interface, or if <span class="new_code">final</span> methods are
|
||||
present in a target class, then a whole new class
|
||||
is created, but one implemeting the same interfaces.
|
||||
If you try to pass this separate class through a type hint that specifies
|
||||
the old concrete class name, it will fail.
|
||||
Code like that insists on type hinting to a class with <span class="new_code">final</span>
|
||||
methods probably cannot be safely tested with mocks.
|
||||
</p>
|
||||
<p>
|
||||
If you want to see the generated code, then simply <span class="new_code">print</span>
|
||||
the output of <span class="new_code">Mock::generate()</span>.
|
||||
Here is the generated code for the <span class="new_code">DatabaseConnection</span>
|
||||
class rather than the interface version...
|
||||
<pre>
|
||||
class MockDatabaseConnection extends DatabaseConnection {
|
||||
public $mock;
|
||||
protected $mocked_methods = array('databaseconnection', 'query', 'selectquery');
|
||||
|
||||
function MockDatabaseConnection() {
|
||||
$this->mock = new SimpleMock();
|
||||
$this->mock->disableExpectationNameChecks();
|
||||
}
|
||||
...
|
||||
function DatabaseConnection() {
|
||||
$args = func_get_args();
|
||||
$result = &$this->mock->invoke("DatabaseConnection", $args);
|
||||
return $result;
|
||||
}
|
||||
function query($sql) {
|
||||
$args = func_get_args();
|
||||
$result = &$this->mock->invoke("query", $args);
|
||||
return $result;
|
||||
}
|
||||
function selectQuery($sql) {
|
||||
$args = func_get_args();
|
||||
$result = &$this->mock->invoke("selectQuery", $args);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Your output may vary depending on the exact version
|
||||
of SimpleTest you are using.
|
||||
</p>
|
||||
<p>
|
||||
Besides the original methods of the class, you will see some extra
|
||||
methods that help testing.
|
||||
More on these later.
|
||||
</p>
|
||||
<p>
|
||||
We can now create instances of the new class within
|
||||
our test case...
|
||||
<pre>
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('database_connection.php');
|
||||
|
||||
Mock::generate('DatabaseConnection');
|
||||
|
||||
class MyTestCase extends UnitTestCase {
|
||||
|
||||
function testSomething() {
|
||||
<strong>$connection = new MockDatabaseConnection();</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The mock version now has all the methods of the original.
|
||||
Also, any type hints will be faithfully preserved.
|
||||
Say our query methods expect a <span class="new_code">Query</span> object...
|
||||
<pre>
|
||||
<strong>class DatabaseConnection {
|
||||
function DatabaseConnection() { }
|
||||
function query(Query $query) { }
|
||||
function selectQuery(Query $query) { }
|
||||
}</strong>
|
||||
</pre>
|
||||
If we now pass the wrong type of object, or worse a non-object...
|
||||
<pre>
|
||||
class MyTestCase extends UnitTestCase {
|
||||
|
||||
function testSomething() {
|
||||
$connection = new MockDatabaseConnection();
|
||||
$connection->query('insert into accounts () values ()');
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
...the code will throw a type violation at you just as the
|
||||
original class would.
|
||||
</p>
|
||||
<p>
|
||||
The mock version now has all the methods of the original.
|
||||
Unfortunately, they all return <span class="new_code">null</span>.
|
||||
As methods that always return <span class="new_code">null</span> are not that useful,
|
||||
we need to be able to set them to something else...
|
||||
</p>
|
||||
<p>
|
||||
<a class="target" name="stub"><h2>Mocks as actors</h2></a>
|
||||
</p>
|
||||
<p>
|
||||
Changing the return value of a method from <span class="new_code">null</span>
|
||||
to something else is pretty easy...
|
||||
<pre>
|
||||
<strong>$connection->returns('query', 37)</strong>
|
||||
</pre>
|
||||
Now every time we call
|
||||
<span class="new_code">$connection->query()</span> we get
|
||||
the result of 37.
|
||||
There is nothing special about 37.
|
||||
The return value can be arbitrarily complicated.
|
||||
</p>
|
||||
<p>
|
||||
Parameters are irrelevant here, we always get the same
|
||||
values back each time once they have been set up this way.
|
||||
That may not sound like a convincing replica of a
|
||||
database connection, but for the half a dozen lines of
|
||||
a test method it is usually all you need.
|
||||
</p>
|
||||
<p>
|
||||
Things aren't always that simple though.
|
||||
One common problem is iterators, where constantly returning
|
||||
the same value could cause an endless loop in the object
|
||||
being tested.
|
||||
For these we need to set up sequences of values.
|
||||
Let's say we have a simple iterator that looks like this...
|
||||
<pre>
|
||||
class Iterator {
|
||||
function Iterator() { }
|
||||
function next() { }
|
||||
}
|
||||
</pre>
|
||||
This is about the simplest iterator you could have.
|
||||
Assuming that this iterator only returns text until it
|
||||
reaches the end, when it returns false, we can simulate it
|
||||
with...
|
||||
<pre>
|
||||
Mock::generate('Iterator');
|
||||
|
||||
class IteratorTest extends UnitTestCase() {
|
||||
|
||||
function testASequence() {<strong>
|
||||
$iterator = new MockIterator();
|
||||
$iterator->returns('next', false);
|
||||
$iterator->returnsAt(0, 'next', 'First string');
|
||||
$iterator->returnsAt(1, 'next', 'Second string');</strong>
|
||||
...
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
When <span class="new_code">next()</span> is called on the
|
||||
<span class="new_code">MockIterator</span> it will first return "First string",
|
||||
on the second call "Second string" will be returned
|
||||
and on any other call <span class="new_code">false</span> will
|
||||
be returned.
|
||||
The sequenced return values take precedence over the constant
|
||||
return value.
|
||||
The constant one is a kind of default if you like.
|
||||
</p>
|
||||
<p>
|
||||
Another tricky situation is an overloaded
|
||||
<span class="new_code">get()</span> operation.
|
||||
An example of this is an information holder with name/value pairs.
|
||||
Say we have a configuration class like...
|
||||
<pre>
|
||||
class Configuration {
|
||||
function Configuration() { ... }
|
||||
function get($key) { ... }
|
||||
}
|
||||
</pre>
|
||||
This is a likely situation for using mock objects, as
|
||||
actual configuration will vary from machine to machine and
|
||||
even from test to test.
|
||||
The problem though is that all the data comes through the
|
||||
<span class="new_code">get()</span> method and yet
|
||||
we want different results for different keys.
|
||||
Luckily the mocks have a filter system...
|
||||
<pre>
|
||||
<strong>$config = &new MockConfiguration();
|
||||
$config->returns('get', 'primary', array('db_host'));
|
||||
$config->returns('get', 'admin', array('db_user'));
|
||||
$config->returns('get', 'secret', array('db_password'));</strong>
|
||||
</pre>
|
||||
The extra parameter is a list of arguments to attempt
|
||||
to match.
|
||||
In this case we are trying to match only one argument which
|
||||
is the look up key.
|
||||
Now when the mock object has the
|
||||
<span class="new_code">get()</span> method invoked
|
||||
like this...
|
||||
<pre>
|
||||
$config->get('db_user')
|
||||
</pre>
|
||||
...it will return "admin".
|
||||
It finds this by attempting to match the calling arguments
|
||||
to its list of returns one after another until
|
||||
a complete match is found.
|
||||
</p>
|
||||
<p>
|
||||
You can set a default argument argument like so...
|
||||
<pre><strong>
|
||||
$config->returns('get', false, array('*'));</strong>
|
||||
</pre>
|
||||
This is not the same as setting the return value without
|
||||
any argument requirements like this...
|
||||
<pre><strong>
|
||||
$config->returns('get', false);</strong>
|
||||
</pre>
|
||||
In the first case it will accept any single argument,
|
||||
but exactly one is required.
|
||||
In the second case any number of arguments will do and
|
||||
it acts as a catchall after all other matches.
|
||||
Note that if we add further single parameter options after
|
||||
the wildcard in the first case, they will be ignored as the wildcard
|
||||
will match first.
|
||||
With complex parameter lists the ordering could be important
|
||||
or else desired matches could be masked by earlier wildcard
|
||||
ones.
|
||||
Declare the most specific matches first if you are not sure.
|
||||
</p>
|
||||
<p>
|
||||
There are times when you want a specific reference to be
|
||||
dished out by the mock rather than a copy or object handle.
|
||||
This a rarity to say the least, but you might be simulating
|
||||
a container that can hold primitives such as strings.
|
||||
For example...
|
||||
<pre>
|
||||
class Pad {
|
||||
function Pad() { }
|
||||
function &note($index) { }
|
||||
}
|
||||
</pre>
|
||||
In this case you can set a reference into the mock's
|
||||
return list...
|
||||
<pre>
|
||||
function testTaskReads() {
|
||||
$note = 'Buy books';
|
||||
$pad = new MockPad();
|
||||
$vector-><strong>returnsByReference(</strong>'note', $note, array(3)<strong>)</strong>;
|
||||
$task = new Task($pad);
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
With this arrangement you know that every time
|
||||
<span class="new_code">$pad->note(3)</span> is
|
||||
called it will return the same <span class="new_code">$note</span> each time,
|
||||
even if it get's modified.
|
||||
</p>
|
||||
<p>
|
||||
These three factors, timing, parameters and whether to copy,
|
||||
can be combined orthogonally.
|
||||
For example...
|
||||
<pre>
|
||||
$buy_books = 'Buy books';
|
||||
$write_code = 'Write code';
|
||||
$pad = new MockPad();
|
||||
$vector-><strong>returnsByReferenceAt(0, 'note', $buy_books, array('*', 3));</strong>
|
||||
$vector-><strong>returnsByReferenceAt(1, 'note', $write_code, array('*', 3));</strong>
|
||||
</pre>
|
||||
This will return a reference to <span class="new_code">$buy_books</span> and
|
||||
then to <span class="new_code">$write_code</span>, but only if two parameters
|
||||
were set the second of which must be the integer 3.
|
||||
That should cover most situations.
|
||||
</p>
|
||||
<p>
|
||||
A final tricky case is one object creating another, known
|
||||
as a factory pattern.
|
||||
Suppose that on a successful query to our imaginary
|
||||
database, a result set is returned as an iterator, with
|
||||
each call to the the iterator's <span class="new_code">next()</span> giving
|
||||
one row until false.
|
||||
This sounds like a simulation nightmare, but in fact it can all
|
||||
be mocked using the mechanics above...
|
||||
<pre>
|
||||
Mock::generate('DatabaseConnection');
|
||||
Mock::generate('ResultIterator');
|
||||
|
||||
class DatabaseTest extends UnitTestCase {
|
||||
|
||||
function testUserFinderReadsResultsFromDatabase() {<strong>
|
||||
$result = new MockResultIterator();
|
||||
$result->returns('next', false);
|
||||
$result->returnsAt(0, 'next', array(1, 'tom'));
|
||||
$result->returnsAt(1, 'next', array(3, 'dick'));
|
||||
$result->returnsAt(2, 'next', array(6, 'harry'));
|
||||
|
||||
$connection = new MockDatabaseConnection();
|
||||
$connection->returns('selectQuery', $result);</strong>
|
||||
|
||||
$finder = new UserFinder(<strong>$connection</strong>);
|
||||
$this->assertIdentical(
|
||||
$finder->findNames(),
|
||||
array('tom', 'dick', 'harry'));
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Now only if our
|
||||
<span class="new_code">$connection</span> is called with the
|
||||
<span class="new_code">query()</span> method will the
|
||||
<span class="new_code">$result</span> be returned that is
|
||||
itself exhausted after the third call to <span class="new_code">next()</span>.
|
||||
This should be enough
|
||||
information for our <span class="new_code">UserFinder</span> class,
|
||||
the class actually
|
||||
being tested here, to come up with goods.
|
||||
A very precise test and not a real database in sight.
|
||||
</p>
|
||||
<p>
|
||||
We could refine this test further by insisting that the correct
|
||||
query is sent...
|
||||
<pre>
|
||||
$connection->returns('selectQuery', $result, array(<strong>'select name, id from people'</strong>));
|
||||
</pre>
|
||||
This is actually a bad idea.
|
||||
</p>
|
||||
<p>
|
||||
We have a <span class="new_code">UserFinder</span> in object land, talking to
|
||||
database tables using a large interface - the whole of SQL.
|
||||
Imagine that we have written a lot of tests that now depend
|
||||
on the exact SQL string passed.
|
||||
These queries could change en masse for all sorts of reasons
|
||||
not related to the specific test.
|
||||
For example the quoting rules could change, a table name could
|
||||
change, a link table added or whatever.
|
||||
This would require the rewriting of every single test any time
|
||||
one of these refactoring is made, yet the intended behaviour has
|
||||
stayed the same.
|
||||
Tests are supposed to help refactoring, not hinder it.
|
||||
I'd certainly like to have a test suite that passes while I change
|
||||
table names.
|
||||
</p>
|
||||
<p>
|
||||
As a rule it is best not to mock a fat interface.
|
||||
</p>
|
||||
<p>
|
||||
By contrast, here is the round trip test...
|
||||
<pre>
|
||||
class DatabaseTest extends UnitTestCase {<strong>
|
||||
function setUp() { ... }
|
||||
function tearDown() { ... }</strong>
|
||||
|
||||
function testUserFinderReadsResultsFromDatabase() {
|
||||
$finder = new UserFinder(<strong>new DatabaseConnection()</strong>);
|
||||
$finder->add('tom');
|
||||
$finder->add('dick');
|
||||
$finder->add('harry');
|
||||
$this->assertIdentical(
|
||||
$finder->findNames(),
|
||||
array('tom', 'dick', 'harry'));
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
This test is immune to schema changes.
|
||||
It will only fail if you actually break the functionality, which
|
||||
is what you want a test to do.
|
||||
</p>
|
||||
<p>
|
||||
The catch is those <span class="new_code">setUp()</span> and <span class="new_code">tearDown()</span>
|
||||
methods that we've rather glossed over.
|
||||
They have to clear out the database tables and ensure that the
|
||||
schema is defined correctly.
|
||||
That can be a chunk of extra work, but you usually have this code
|
||||
lying around anyway for deployment purposes.
|
||||
</p>
|
||||
<p>
|
||||
One place where you definitely need a mock is simulating failures.
|
||||
Say the database goes down while <span class="new_code">UserFinder</span> is doing
|
||||
it's work.
|
||||
Does <span class="new_code">UserFinder</span> behave well...?
|
||||
<pre>
|
||||
class DatabaseTest extends UnitTestCase {
|
||||
|
||||
function testUserFinder() {
|
||||
$connection = new MockDatabaseConnection();<strong>
|
||||
$connection->throwOn('selectQuery', new TimedOut('Ouch!'));</strong>
|
||||
$alert = new MockAlerts();<strong>
|
||||
$alert->expectOnce('notify', 'Database is busy - please retry');</strong>
|
||||
$finder = new UserFinder($connection, $alert);
|
||||
$this->assertIdentical($finder->findNames(), array());
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
We've passed the <span class="new_code">UserFinder</span> an <span class="new_code">$alert</span>
|
||||
object.
|
||||
This is going to do some kind of pretty notifications in the
|
||||
user interface in the event of an error.
|
||||
We'd rather not sprinkle our code with hard wired <span class="new_code">print</span>
|
||||
statements if we can avoid it.
|
||||
Wrapping the means of output means we can use this code anywhere.
|
||||
It also makes testing easier.
|
||||
</p>
|
||||
<p>
|
||||
To pass this test, the finder has to write a nice user friendly
|
||||
message to <span class="new_code">$alert</span>, rather than propogating the exception.
|
||||
So far, so good.
|
||||
</p>
|
||||
<p>
|
||||
How do we get the mock <span class="new_code">DatabaseConnection</span> to throw an exception?
|
||||
We generate the exception using the <span class="new_code">throwOn</span> method
|
||||
on the mock.
|
||||
</p>
|
||||
<p>
|
||||
Finally, what if the method you want to simulate does not exist yet?
|
||||
If you set a return value on a method that is not there, SimpleTest
|
||||
will throw an error.
|
||||
What if you are using <span class="new_code">__call()</span> to simulate dynamic methods?
|
||||
</p>
|
||||
<p>
|
||||
Objects with dynamic interfaces, using <span class="new_code">__call</span>, can
|
||||
be problematic with the current mock objects implementation.
|
||||
You can mock the <span class="new_code">__call()</span> method, but this is ugly.
|
||||
Why should a test know anything about such low level implementation details?
|
||||
It just wants to simulate the call.
|
||||
</p>
|
||||
<p>
|
||||
The way round this is to add extra methods to the mock when
|
||||
generating it.
|
||||
<pre>
|
||||
<strong>Mock::generate('DatabaseConnection', 'MockDatabaseConnection', array('setOptions'));</strong>
|
||||
</pre>
|
||||
In a large test suite this could cause trouble, as you probably
|
||||
already have a mock version of the class called
|
||||
<span class="new_code">MockDatabaseConnection</span> without the extra methods.
|
||||
The code generator will not generate a mock version of the class if
|
||||
one of the same name already exists.
|
||||
You will confusingly fail to see your method if another definition
|
||||
was run first.
|
||||
</p>
|
||||
<p>
|
||||
To cope with this, SimpleTest allows you to choose any name for the
|
||||
new class at the same time as you add the extra methods.
|
||||
<pre>
|
||||
Mock::generate('DatabaseConnection', <strong>'MockDatabaseConnectionWithOptions'</strong>, array('setOptions'));
|
||||
</pre>
|
||||
Here the mock will behave as if the <span class="new_code">setOptions()</span>
|
||||
existed in the original class.
|
||||
</p>
|
||||
<p>
|
||||
Mock objects can only be used within test cases, as upon expectations
|
||||
they send messages straight to the currently running test case.
|
||||
Creating them outside a test case will cause a run time error
|
||||
when an expectation is triggered and there is no running test case
|
||||
for the message to end up.
|
||||
We cover expectations next.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="expectations"></a>Mocks as critics</h2>
|
||||
<p>
|
||||
Although the server stubs approach insulates your tests from
|
||||
real world disruption, it is only half the benefit.
|
||||
You can have the class under test receiving the required
|
||||
messages, but is your new class sending correct ones?
|
||||
Testing this can get messy without a mock objects library.
|
||||
</p>
|
||||
<p>
|
||||
By way of example, let's take a simple <span class="new_code">PageController</span>
|
||||
class to handle a credit card payment form...
|
||||
<pre>
|
||||
class PaymentForm extends PageController {
|
||||
function __construct($alert, $payment_gateway) { ... }
|
||||
function makePayment($request) { ... }
|
||||
}
|
||||
</pre>
|
||||
This class takes a <span class="new_code">PaymentGateway</span> to actually talk
|
||||
to the bank.
|
||||
It also takes an <span class="new_code">Alert</span> object to handle errors.
|
||||
This class talks to the page or template.
|
||||
It's responsible for painting the error message and highlighting any
|
||||
form fields that are incorrect.
|
||||
</p>
|
||||
<p>
|
||||
It might look something like...
|
||||
<pre>
|
||||
class Alert {
|
||||
function warn($warning, $id) {
|
||||
print '<div class="warning">' . $warning . '</div>';
|
||||
print '<style type="text/css">#' . $id . ' { background-color: red }</style>';
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
Our interest is in the <span class="new_code">makePayment()</span> method.
|
||||
If we fail to enter a "CVV2" number (the three digit number
|
||||
on the back of the credit card), we want to show an error rather than
|
||||
try to process the payment.
|
||||
In test form...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('payment_form.php');
|
||||
Mock::generate('Alert');
|
||||
Mock::generate('PaymentGateway');
|
||||
|
||||
class PaymentFormFailuresShouldBeGraceful extends UnitTestCase {
|
||||
|
||||
function testMissingCvv2CausesAlert() {
|
||||
$alert = new MockAlert();
|
||||
<strong>$alert->expectOnce(
|
||||
'warn',
|
||||
array('Missing three digit security code', 'cvv2'));</strong>
|
||||
$controller = new PaymentForm(<strong>$alert</strong>, new MockPaymentGateway());
|
||||
$controller->makePayment($this->requestWithMissingCvv2());
|
||||
}
|
||||
|
||||
function requestWithMissingCvv2() { ... }
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
The first question you may be asking is, where are the assertions?
|
||||
</p>
|
||||
<p>
|
||||
The call to <span class="new_code">expectOnce('warn', array(...))</span> instructs the mock
|
||||
to expect a call to <span class="new_code">warn()</span> before the test ends.
|
||||
When it gets a call to <span class="new_code">warn()</span>, it checks the arguments.
|
||||
If the arguments don't match, then a failure is generated.
|
||||
It also fails if the method is never called at all.
|
||||
</p>
|
||||
<p>
|
||||
The test above not only asserts that <span class="new_code">warn</span> was called,
|
||||
but that it received the string "Missing three digit security code"
|
||||
and also the tag "cvv2".
|
||||
The equivalent of <span class="new_code">assertIdentical()</span> is applied to both
|
||||
fields when the parameters are compared.
|
||||
</p>
|
||||
<p>
|
||||
If you are not interested in the actual message, and we are not
|
||||
for user interface code that changes often, we can skip that
|
||||
parameter with the "*" operator...
|
||||
<pre>
|
||||
class PaymentFormFailuresShouldBeGraceful extends UnitTestCase {
|
||||
|
||||
function testMissingCvv2CausesAlert() {
|
||||
$alert = new MockAlert();
|
||||
$alert->expectOnce('warn', array(<strong>'*'</strong>, 'cvv2'));
|
||||
$controller = new PaymentForm($alert, new MockPaymentGateway());
|
||||
$controller->makePayment($this->requestWithMissingCvv2());
|
||||
}
|
||||
|
||||
function requestWithMissingCvv2() { ... }
|
||||
}
|
||||
</pre>
|
||||
We can weaken the test further by missing
|
||||
out the parameters array...
|
||||
<pre>
|
||||
function testMissingCvv2CausesAlert() {
|
||||
$alert = new MockAlert();
|
||||
<strong>$alert->expectOnce('warn');</strong>
|
||||
$controller = new PaymentForm($alert, new MockPaymentGateway());
|
||||
$controller->makePayment($this->requestWithMissingCvv2());
|
||||
}
|
||||
</pre>
|
||||
This will only test that the method is called,
|
||||
which is a bit drastic in this case.
|
||||
Later on, we'll see how we can weaken the expectations more precisely.
|
||||
</p>
|
||||
<p>
|
||||
Tests without assertions can be both compact and very expressive.
|
||||
Because we intercept the call on the way into an object, here of
|
||||
the <span class="new_code">Alert</span> class, we avoid having to assert its state
|
||||
afterwards.
|
||||
This not only avoids the assertions in the tests, but also having
|
||||
to add extra test only accessors to the original code.
|
||||
If you catch yourself adding such accessors, called "state based testing",
|
||||
it's probably time to consider using mocks in the tests.
|
||||
This is called "behaviour based testing", and is normally superior.
|
||||
</p>
|
||||
<p>
|
||||
Let's add another test.
|
||||
Let's make sure that we don't even attempt a payment without a CVV2...
|
||||
<pre>
|
||||
class PaymentFormFailuresShouldBeGraceful extends UnitTestCase {
|
||||
|
||||
function testMissingCvv2CausesAlert() { ... }
|
||||
|
||||
function testNoPaymentAttemptedWithMissingCvv2() {
|
||||
$payment_gateway = new MockPaymentGateway();
|
||||
<strong>$payment_gateway->expectNever('pay');</strong>
|
||||
$controller = new PaymentForm(new MockAlert(), $payment_gateway);
|
||||
$controller->makePayment($this->requestWithMissingCvv2());
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
Asserting a negative can be very hard in tests, but
|
||||
<span class="new_code">expectNever()</span> makes it easy.
|
||||
</p>
|
||||
<p>
|
||||
<span class="new_code">expectOnce()</span> and <span class="new_code">expectNever()</span> are
|
||||
sufficient for most tests, but
|
||||
occasionally you want to test multiple events.
|
||||
Normally for usability purposes we want all missing fields
|
||||
in the form to light up, not just the first one.
|
||||
This means that we should get multiple calls to
|
||||
<span class="new_code">Alert::warn()</span>, not just one...
|
||||
<pre>
|
||||
function testAllRequiredFieldsHighlightedOnEmptyRequest() {
|
||||
$alert = new MockAlert();<strong>
|
||||
$alert->expectAt(0, 'warn', array('*', 'cc_number'));
|
||||
$alert->expectAt(1, 'warn', array('*', 'expiry'));
|
||||
$alert->expectAt(2, 'warn', array('*', 'cvv2'));
|
||||
$alert->expectAt(3, 'warn', array('*', 'card_holder'));
|
||||
$alert->expectAt(4, 'warn', array('*', 'address'));
|
||||
$alert->expectAt(5, 'warn', array('*', 'postcode'));
|
||||
$alert->expectAt(6, 'warn', array('*', 'country'));
|
||||
$alert->expectCallCount('warn', 7);</strong>
|
||||
$controller = new PaymentForm($alert, new MockPaymentGateway());
|
||||
$controller->makePayment($this->requestWithMissingCvv2());
|
||||
}
|
||||
</pre>
|
||||
The counter in <span class="new_code">expectAt()</span> is the number of times
|
||||
the method has been called already.
|
||||
Here we are asserting that every field will be highlighted.
|
||||
</p>
|
||||
<p>
|
||||
Note that we are forced to assert the order too.
|
||||
SimpleTest does not yet have a way to avoid this, but
|
||||
this will be fixed in future versions.
|
||||
</p>
|
||||
<p>
|
||||
Here is the full list of expectations you can set on a mock object
|
||||
in <a href="http://simpletest.org/">SimpleTest</a>.
|
||||
As with the assertions, these methods take an optional failure message.
|
||||
<table>
|
||||
<thead><tr>
|
||||
<th>Expectation</th>
|
||||
<th>Description</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span class="new_code">expect($method, $args)</span></td>
|
||||
<td>Arguments must match if called</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectAt($timing, $method, $args)</span></td>
|
||||
<td>Arguments must match when called on the <span class="new_code">$timing</span>'th time</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectCallCount($method, $count)</span></td>
|
||||
<td>The method must be called exactly this many times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectMaximumCallCount($method, $count)</span></td>
|
||||
<td>Call this method no more than <span class="new_code">$count</span> times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectMinimumCallCount($method, $count)</span></td>
|
||||
<td>Must be called at least <span class="new_code">$count</span> times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectNever($method)</span></td>
|
||||
<td>Must never be called</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectOnce($method, $args)</span></td>
|
||||
<td>Must be called once and with the expected arguments if supplied</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="new_code">expectAtLeastOnce($method, $args)</span></td>
|
||||
<td>Must be called at least once, and always with any expected arguments</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
Where the parameters are...
|
||||
<dl>
|
||||
<dt class="new_code">$method</dt>
|
||||
<dd>The method name, as a string, to apply the condition to.</dd>
|
||||
<dt class="new_code">$args</dt>
|
||||
<dd>
|
||||
The arguments as a list. Wildcards can be included in the same
|
||||
manner as for <span class="new_code">setReturn()</span>.
|
||||
This argument is optional for <span class="new_code">expectOnce()</span>
|
||||
and <span class="new_code">expectAtLeastOnce()</span>.
|
||||
</dd>
|
||||
<dt class="new_code">$timing</dt>
|
||||
<dd>
|
||||
The only point in time to test the condition.
|
||||
The first call starts at zero and the count is for
|
||||
each method independently.
|
||||
</dd>
|
||||
<dt class="new_code">$count</dt>
|
||||
<dd>The number of calls expected.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
If you have just one call in your test, make sure you're using
|
||||
<span class="new_code">expectOnce</span>.<br>
|
||||
Using <span class="new_code">$mocked->expectAt(0, 'method', 'args);</span>
|
||||
on its own will allow the method to never be called.
|
||||
Checking the arguments and the overall call count
|
||||
are currently independant.
|
||||
Add an <span class="new_code">expectCallCount()</span> expectation when you
|
||||
are using <span class="new_code">expectAt()</span> unless zero calls is allowed.
|
||||
</p>
|
||||
<p>
|
||||
Like the assertions within test cases, all of the expectations
|
||||
can take a message override as an extra parameter.
|
||||
Also the original failure message can be embedded in the output
|
||||
as "%s".
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
The original
|
||||
<a href="http://www.mockobjects.com/">Mock objects</a> paper.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest home page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<span class="chosen">Mock objects</span>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,487 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>
|
||||
Overview and feature list for the SimpleTest PHP unit tester and web tester
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<span class="chosen">Overview</span>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Overview of SimpleTest</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#summary">Quick summary</a>
|
||||
of the SimpleTest tool for PHP.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#features">List of features</a>,
|
||||
both current ones and those planned.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
<h2>
|
||||
<a class="target" name="summary"></a>What is SimpleTest?</h2>
|
||||
<p>
|
||||
The heart of SimpleTest is a testing framework built around
|
||||
test case classes.
|
||||
These are written as extensions of base test case classes,
|
||||
each extended with methods that actually contain test code.
|
||||
Each test method of a test case class is written to invoke
|
||||
various assertions that the developer expects to be true such as
|
||||
<span class="new_code">assertEqual()</span>.
|
||||
If the expectation is correct, then a successful result is
|
||||
dispatched to the observing test reporter, but any failure
|
||||
or unexpected exception triggers an alert and a description
|
||||
of the mismatch.
|
||||
These test case declarations are transformed into executable
|
||||
test scripts by including a SimpleTest aurorun.php file.
|
||||
</p>
|
||||
<p>
|
||||
These documents apply to SimpleTest version 1.1, although we
|
||||
try hard to maintain compatibility between versions.
|
||||
If you get a test failure after an upgrade, check out the
|
||||
file "HELP_MY_TESTS_DONT_WORK_ANYMORE" in the
|
||||
simpletest directory to see if a feature you are using
|
||||
has since been deprecated and later removed.
|
||||
</p>
|
||||
<p>
|
||||
A <a href="unit_test_documentation.html">test case</a> looks like this...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
class <strong>CanAddUp</strong> extends UnitTestCase {<strong>
|
||||
function testOneAndOneMakesTwo() {
|
||||
$this->assertEqual(1 + 1, 2);
|
||||
}</strong>
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
Tests are grouped into test cases, which are just
|
||||
PHP classes that extend <span class="new_code">UnitTestCase</span>
|
||||
or <span class="new_code">WebTestCase</span>.
|
||||
The tests themselves are just normal methods that start
|
||||
their name with the letters "test".
|
||||
You can have as many test cases as you want in a test
|
||||
script and each test case can have as many test methods
|
||||
as it wants too.
|
||||
</p>
|
||||
<p>
|
||||
This test script is immediately runnable.
|
||||
You just invoke it on the command line like so...
|
||||
<pre class="shell">
|
||||
php adding_test.php
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
When run on the command line you should see something like...
|
||||
<pre class="shell">
|
||||
adding_test.php
|
||||
OK
|
||||
Test cases run: 1/1, Passes: 1, Failures: 0, Exceptions: 0
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
If you place it on a web server and point your
|
||||
web browser at it...
|
||||
<div class="demo">
|
||||
<h1>adding_test.php</h1>
|
||||
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
||||
<strong>6</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
|
||||
</div>
|
||||
</p>
|
||||
<p>
|
||||
Of course this is a silly example.
|
||||
A more realistic example might be...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('log.php');
|
||||
|
||||
class <strong>TestOfLogging</strong> extends UnitTestCase {
|
||||
function testWillCreateLogFileOnFirstMessage() {
|
||||
$log = new Log('my.log');
|
||||
$this->assertFalse(file_exists('my.log'));
|
||||
$log->message('Hello');
|
||||
$this->assertTrue(file_exists('my.log'));
|
||||
}</strong>
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
This tool is designed for the developer.
|
||||
The target audience of this tool is anyone developing a small
|
||||
to medium PHP application, including developers new to
|
||||
unit and web regression testing.
|
||||
The core principles are ease of use first, with extendibility and
|
||||
essential features.
|
||||
</p>
|
||||
<p>
|
||||
Tests are written in the PHP language itself more or less
|
||||
as the application itself is built.
|
||||
The advantage of using PHP as the testing language is that
|
||||
there are no new languages to learn, testing can start straight away,
|
||||
and the developer can test any part of the code.
|
||||
Basically, all parts that can be accessed by the application code can also be
|
||||
accessed by the test code when they are in the same programming language.
|
||||
</p>
|
||||
<p>
|
||||
The simplest type of test case is the
|
||||
<a href="unit_tester_documentation.html">UnitTestCase</a>.
|
||||
This class of test case includes standard tests for equality,
|
||||
references and pattern matching.
|
||||
All these test the typical expectations of what you would
|
||||
expect the result of a function or method to be.
|
||||
This is by far the most common type of test in the daily
|
||||
routine of development, making up about 95% of test cases.
|
||||
</p>
|
||||
<p>
|
||||
The top level task of a web application though is not to
|
||||
produce correct output from its methods and objects, but
|
||||
to generate web pages.
|
||||
The <a href="web_tester_documentation.html">WebTestCase</a> class tests web
|
||||
pages.
|
||||
It simulates a web browser requesting a page, complete with
|
||||
cookies, proxies, secure connections, authentication, forms, frames and most
|
||||
navigation elements.
|
||||
With this type of test case, the developer can assert that
|
||||
information is present in the page and that forms and
|
||||
sessions are handled correctly.
|
||||
</p>
|
||||
<p>
|
||||
A <a href="web_tester_documentation.html">WebTestCase</a> looks like this...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
require_once('simpletest/web_tester.php');
|
||||
|
||||
class <strong>MySiteTest</strong> extends WebTestCase {
|
||||
<strong>
|
||||
function testHomePageHasContactDetailsLink() {
|
||||
$this->get('http://www.my-site.com/index.php');
|
||||
$this->assertTitle('My Home Page');
|
||||
$this->clickLink('Contact');
|
||||
$this->assertTitle('Contact me');
|
||||
$this->assertText('/Email me at/');
|
||||
}</strong>
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="features"></a>Feature list</h2>
|
||||
<p>
|
||||
The following is a very rough outline of past and future features
|
||||
and their expected point of release.
|
||||
I am afraid it is liable to change without warning, as meeting the
|
||||
milestones rather depends on time available.
|
||||
</p>
|
||||
<p>
|
||||
Green stuff has been coded, but not necessarily released yet.
|
||||
If you have a pressing need for a green but unreleased feature
|
||||
then you should check-out the code from Sourceforge SVN directly.
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Feature</th>
|
||||
<th>Description</th>
|
||||
<th>Release</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Unit test case</td>
|
||||
<td>Core test case class and assertions</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Html display</td>
|
||||
<td>Simplest possible display</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Autoloading of test cases</td>
|
||||
<td>
|
||||
Reading a file with test cases and loading them into a
|
||||
group test automatically
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mock objects</td>
|
||||
<td>
|
||||
Objects capable of simulating other objects removing
|
||||
test dependencies
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Web test case</td>
|
||||
<td>Allows link following and title tag matching</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Partial mocks</td>
|
||||
<td>
|
||||
Mocking parts of a class for testing less than a class
|
||||
or for complex simulations
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Web cookie handling</td>
|
||||
<td>Correct handling of cookies when fetching pages</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Following redirects</td>
|
||||
<td>Page fetching automatically follows 300 redirects</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Form parsing</td>
|
||||
<td>Ability to submit simple forms and read default form values</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Command line interface</td>
|
||||
<td>Test display without the need of a web browser</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exposure of expectation classes</td>
|
||||
<td>Can create precise tests with mocks as well as test cases</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>XML output and parsing</td>
|
||||
<td>
|
||||
Allows multi host testing and the integration of acceptance
|
||||
testing extensions
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Browser component</td>
|
||||
<td>
|
||||
Exposure of lower level web browser interface for more
|
||||
detailed test cases
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HTTP authentication</td>
|
||||
<td>
|
||||
Fetching protected web pages with basic authentication
|
||||
only
|
||||
</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SSL support</td>
|
||||
<td>Can connect to https: pages</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Proxy support</td>
|
||||
<td>Can connect via. common proxies</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Frames support</td>
|
||||
<td>Handling of frames in web test cases</td>
|
||||
<td style="color: green;">1.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>File upload testing</td>
|
||||
<td>Can simulate the input type file tag</td>
|
||||
<td style="color: green;">1.0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mocking interfaces</td>
|
||||
<td>
|
||||
Can generate mock objects to interfaces as well as classes
|
||||
and class interfaces are carried for type hints
|
||||
</td>
|
||||
<td style="color: green;">1.0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Testing exceptions</td>
|
||||
<td>Similar to testing PHP errors</td>
|
||||
<td style="color: green;">1.0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HTML label support</td>
|
||||
<td>Can access all controls using the visual label</td>
|
||||
<td style="color: green;">1.0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Base tag support</td>
|
||||
<td>Respects page base tag when clicking</td>
|
||||
<td style="color: green;">1.0.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PHP 5 E_STRICT compliant</td>
|
||||
<td>PHP 5 only version that works with the E_STRICT error level</td>
|
||||
<td style="color: green;">1.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alternate HTML parsers</td>
|
||||
<td>Can detect compiled parsers for performance improvements</td>
|
||||
<td style="color: green;">1.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>REST support</td>
|
||||
<td>Support for REST verbs as put(), delete(), etc.</td>
|
||||
<td style="color: green;">1.1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BDD style fixtures</td>
|
||||
<td>Can import fixtures using a mixin like given() method</td>
|
||||
<td style="color: red;">1.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Plug-in architecture</td>
|
||||
<td>Automatic import of extensions including command line options</td>
|
||||
<td style="color: red;">1.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reporting machinery enhancements</td>
|
||||
<td>Improved message passing for better cooperation with IDEs</td>
|
||||
<td style="color: red;">1.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fluent mock interface</td>
|
||||
<td>More flexible and concise mock objects</td>
|
||||
<td style="color: red;">1.6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Localisation</td>
|
||||
<td>Messages abstracted and code generated as well as UTF support</td>
|
||||
<td style="color: red;">1.6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSS selectors</td>
|
||||
<td>HTML content can be examined using CSS selectors</td>
|
||||
<td style="color: red;">1.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HTML table assertions</td>
|
||||
<td>Can match HTML or other table elements to expectations</td>
|
||||
<td style="color: red;">1.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unified acceptance testing model</td>
|
||||
<td>Content searchable through selectors combined with expectations</td>
|
||||
<td style="color: red;">1.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DatabaseTestCase</td>
|
||||
<td>SQL selectors and DB drivers</td>
|
||||
<td style="color: red;">1.7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IFrame support</td>
|
||||
<td>Reads IFrame content that can be refreshed</td>
|
||||
<td style="color: red;">1.8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Integrated Selenium support</td>
|
||||
<td>Easy to use built in Selenium driver and tutorial or similar browser automation</td>
|
||||
<td style="color: red;">1.9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Code coverage</td>
|
||||
<td>Reports using the bundled tool when using XDebug</td>
|
||||
<td style="color: red;">1.9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deprecation of old methods</td>
|
||||
<td>Simpler interface for SimpleTest2</td>
|
||||
<td style="color: red;">2.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Javascript suport</td>
|
||||
<td>Use of PECL module to add Javascript to the native browser</td>
|
||||
<td style="color: red;">3.0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
PHP 5 migration is complete, which means that only PHP 5.0.3+
|
||||
will be supported in SimpleTest version 1.1+.
|
||||
Earlier versions of SimpleTest are compatible with PHP 4.2 up to
|
||||
PHP 5 (non E_STRICT).
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
<a href="unit_test_documentation.html">Documentation for SimpleTest</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.lastcraft.com/first_test_tutorial.php">How to write PHP test cases</a>
|
||||
is a fairly advanced tutorial.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://simpletest.org/api/">SimpleTest API</a> from phpdoc.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<span class="chosen">Overview</span>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,457 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest for PHP partial mocks documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<span class="chosen">Partial mocks</span>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Partial mock objects documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#inject">The mock injection problem</a>.
|
||||
</li>
|
||||
<li>
|
||||
Moving creation to a <a href="#creation">protected factory</a> method.
|
||||
</li>
|
||||
<li>
|
||||
<a href="#partial">Partial mocks</a> generate subclasses.
|
||||
</li>
|
||||
<li>
|
||||
Partial mocks <a href="#less">test less than a class</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
|
||||
<p>
|
||||
A partial mock is simply a pattern to alleviate a specific problem
|
||||
in testing with mock objects,
|
||||
that of getting mock objects into tight corners.
|
||||
It's quite a limited tool and possibly not even a good idea.
|
||||
It is included with SimpleTest because I have found it useful
|
||||
on more than one occasion and has saved a lot of work at that point.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="inject"></a>The mock injection problem</h2>
|
||||
<p>
|
||||
When one object uses another it is very simple to just pass a mock
|
||||
version in already set up with its expectations.
|
||||
Things are rather tricker if one object creates another and the
|
||||
creator is the one you want to test.
|
||||
This means that the created object should be mocked, but we can
|
||||
hardly tell our class under test to create a mock instead.
|
||||
The tested class doesn't even know it is running inside a test
|
||||
after all.
|
||||
</p>
|
||||
<p>
|
||||
For example, suppose we are building a telnet client and it
|
||||
needs to create a network socket to pass its messages.
|
||||
The connection method might look something like...
|
||||
<pre>
|
||||
<strong><?php
|
||||
require_once('socket.php');
|
||||
|
||||
class Telnet {
|
||||
...
|
||||
function connect($ip, $port, $username, $password) {
|
||||
$socket = new Socket($ip, $port);
|
||||
$socket->read( ... );
|
||||
...
|
||||
}
|
||||
}
|
||||
?></strong>
|
||||
</pre>
|
||||
We would really like to have a mock object version of the socket
|
||||
here, what can we do?
|
||||
</p>
|
||||
<p>
|
||||
The first solution is to pass the socket in as a parameter,
|
||||
forcing the creation up a level.
|
||||
Having the client handle this is actually a very good approach
|
||||
if you can manage it and should lead to factoring the creation from
|
||||
the doing.
|
||||
In fact, this is one way in which testing with mock objects actually
|
||||
forces you to code more tightly focused solutions.
|
||||
They improve your programming.
|
||||
</p>
|
||||
<p>
|
||||
Here this would be...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('socket.php');
|
||||
|
||||
class Telnet {
|
||||
...
|
||||
<strong>function connect($socket, $username, $password) {
|
||||
$socket->read( ... );
|
||||
...
|
||||
}</strong>
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
This means that the test code is typical for a test involving
|
||||
mock objects.
|
||||
<pre>
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {<strong>
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$telnet = new Telnet();
|
||||
$telnet->connect($socket, 'Me', 'Secret');
|
||||
...</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
It is pretty obvious though that one level is all you can go.
|
||||
You would hardly want your top level application creating
|
||||
every low level file, socket and database connection ever
|
||||
needed.
|
||||
It wouldn't know the constructor parameters anyway.
|
||||
</p>
|
||||
<p>
|
||||
The next simplest compromise is to have the created object passed
|
||||
in as an optional parameter...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('socket.php');
|
||||
|
||||
class Telnet {
|
||||
...<strong>
|
||||
function connect($ip, $port, $username, $password, $socket = false) {
|
||||
if (! $socket) {
|
||||
$socket = new Socket($ip, $port);
|
||||
}
|
||||
$socket->read( ... );</strong>
|
||||
...
|
||||
return $socket;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
For a quick solution this is usually good enough.
|
||||
The test now looks almost the same as if the parameter
|
||||
was formally passed...
|
||||
<pre>
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {<strong>
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$telnet = new Telnet();
|
||||
$telnet->connect('127.0.0.1', 21, 'Me', 'Secret', $socket);
|
||||
...</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The problem with this approach is its untidiness.
|
||||
There is test code in the main class and parameters passed
|
||||
in the test case that are never used.
|
||||
This is a quick and dirty approach, but nevertheless effective
|
||||
in most situations.
|
||||
</p>
|
||||
<p>
|
||||
The next method is to pass in a factory object to do the creation...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('socket.php');
|
||||
|
||||
class Telnet {<strong>
|
||||
function Telnet($network) {
|
||||
$this->_network = $network;
|
||||
}</strong>
|
||||
...
|
||||
function connect($ip, $port, $username, $password) {<strong>
|
||||
$socket = $this->_network->createSocket($ip, $port);
|
||||
$socket->read( ... );</strong>
|
||||
...
|
||||
return $socket;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
This is probably the most highly factored answer as creation
|
||||
is now moved into a small specialist class.
|
||||
The networking factory can now be tested separately, but mocked
|
||||
easily when we are testing the telnet class...
|
||||
<pre>
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {<strong>
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$network = new MockNetwork();
|
||||
$network->returnsByReference('createSocket', $socket);
|
||||
$telnet = new Telnet($network);
|
||||
$telnet->connect('127.0.0.1', 21, 'Me', 'Secret');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The downside is that we are adding a lot more classes to the
|
||||
library.
|
||||
Also we are passing a lot of factories around which will
|
||||
make the code a little less intuitive.
|
||||
The most flexible solution, but the most complex.
|
||||
</p>
|
||||
<p>
|
||||
Well techniques like "Dependency Injection" tackle the problem of
|
||||
instantiating a lot of constructor parameters.
|
||||
Unfortunately knowledge of this pattern is not widespread, and if you
|
||||
are trying to get older code to work, rearchitecting the whole
|
||||
application is not really an option.
|
||||
</p>
|
||||
<p>
|
||||
Is there a middle ground?
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="creation"></a>Protected factory method</h2>
|
||||
<p>
|
||||
There is a way we can circumvent the problem without creating
|
||||
any new application classes, but it involves creating a subclass
|
||||
when we do the actual testing.
|
||||
Firstly we move the socket creation into its own method...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('socket.php');
|
||||
|
||||
class Telnet {
|
||||
...
|
||||
function connect($ip, $port, $username, $password) {
|
||||
<strong>$socket = $this->createSocket($ip, $port);</strong>
|
||||
$socket->read( ... );
|
||||
...
|
||||
}<strong>
|
||||
|
||||
protected function createSocket($ip, $port) {
|
||||
return new Socket($ip, $port);
|
||||
}</strong>
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
This is a pretty safe step even for very tangled legacy code.
|
||||
This is the only change we make to the application.
|
||||
</p>
|
||||
<p>
|
||||
For the test case we have to create a subclass so that
|
||||
we can intercept the socket creation...
|
||||
<pre>
|
||||
<strong>class TelnetTestVersion extends Telnet {
|
||||
var $mock;
|
||||
|
||||
function TelnetTestVersion($mock) {
|
||||
$this->mock = $mock;
|
||||
$this->Telnet();
|
||||
}
|
||||
|
||||
protected function createSocket() {
|
||||
return $this->mock;
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
Here I have passed the mock in the constructor, but a
|
||||
setter would have done just as well.
|
||||
Note that the mock was set into the object variable
|
||||
before the constructor was chained.
|
||||
This is necessary in case the constructor calls
|
||||
<span class="new_code">connect()</span>.
|
||||
Otherwise it could get a null value from
|
||||
<span class="new_code">createSocket()</span>.
|
||||
</p>
|
||||
<p>
|
||||
After the completion of all of this extra work the
|
||||
actual test case is fairly easy.
|
||||
We just test our new class instead...
|
||||
<pre>
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {<strong>
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$telnet = new TelnetTestVersion($socket);
|
||||
$telnet->connect('127.0.0.1', 21, 'Me', 'Secret');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The new class is very simple of course.
|
||||
It just sets up a return value, rather like a mock.
|
||||
It would be nice if it also checked the incoming parameters
|
||||
as well.
|
||||
Just like a mock.
|
||||
It seems we are likely to do this often, can
|
||||
we automate the subclass creation?
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="partial"></a>A partial mock</h2>
|
||||
<p>
|
||||
Of course the answer is "yes" or I would have stopped writing
|
||||
this by now!
|
||||
The previous test case was a lot of work, but we can
|
||||
generate the subclass using a similar approach to the mock objects.
|
||||
</p>
|
||||
<p>
|
||||
Here is the partial mock version of the test...
|
||||
<pre>
|
||||
<strong>Mock::generatePartial(
|
||||
'Telnet',
|
||||
'TelnetTestVersion',
|
||||
array('createSocket'));</strong>
|
||||
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {<strong>
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$telnet = new TelnetTestVersion();
|
||||
$telnet->setReturnReference('createSocket', $socket);
|
||||
$telnet->Telnet();
|
||||
$telnet->connect('127.0.0.1', 21, 'Me', 'Secret');</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
The partial mock is a subclass of the original with
|
||||
selected methods "knocked out" with test
|
||||
versions.
|
||||
The <span class="new_code">generatePartial()</span> call
|
||||
takes three parameters: the class to be subclassed,
|
||||
the new test class name and a list of methods to mock.
|
||||
</p>
|
||||
<p>
|
||||
Instantiating the resulting objects is slightly tricky.
|
||||
The only constructor parameter of a partial mock is
|
||||
the unit tester reference.
|
||||
As with the normal mock objects this is needed for sending
|
||||
test results in response to checked expectations.
|
||||
</p>
|
||||
<p>
|
||||
The original constructor is not run yet.
|
||||
This is necessary in case the constructor is going to
|
||||
make use of the as yet unset mocked methods.
|
||||
We set any return values at this point and then run the
|
||||
constructor with its normal parameters.
|
||||
This three step construction of "new", followed
|
||||
by setting up the methods, followed by running the constructor
|
||||
proper is what distinguishes the partial mock code.
|
||||
</p>
|
||||
<p>
|
||||
Apart from construction, all of the mocked methods have
|
||||
the same features as mock objects and all of the unmocked
|
||||
methods behave as before.
|
||||
We can set expectations very easily...
|
||||
<pre>
|
||||
class TelnetTest extends UnitTestCase {
|
||||
...
|
||||
function testConnection() {
|
||||
$socket = new MockSocket();
|
||||
...
|
||||
$telnet = new TelnetTestVersion();
|
||||
$telnet->setReturnReference('createSocket', $socket);
|
||||
<strong>$telnet->expectOnce('createSocket', array('127.0.0.1', 21));</strong>
|
||||
$telnet->Telnet();
|
||||
$telnet->connect('127.0.0.1', 21, 'Me', 'Secret');
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Partial mocks are not used often.
|
||||
I consider them transitory.
|
||||
Useful while refactoring, but once the application has
|
||||
all of it's dependencies nicely separated then the
|
||||
partial mocks can wither away.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="less"></a>Testing less than a class</h2>
|
||||
<p>
|
||||
The mocked out methods don't have to be factory methods,
|
||||
they could be any sort of method.
|
||||
In this way partial mocks allow us to take control of any part of
|
||||
a class except the constructor.
|
||||
We could even go as far as to mock every method
|
||||
except one we actually want to test.
|
||||
</p>
|
||||
<p>
|
||||
This last situation is all rather hypothetical, as I've hardly
|
||||
tried it.
|
||||
I am a little worried that
|
||||
forcing object granularity may be better for the code quality.
|
||||
I personally use partial mocks as a way of overriding creation
|
||||
or for occasional testing of the TemplateMethod pattern.
|
||||
</p>
|
||||
<p>
|
||||
It's all going to come down to the coding standards of your
|
||||
project to decide if you allow test mechanisms like this.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://simpletest.org/api/">Full API for SimpleTest</a>
|
||||
from the PHPDoc.
|
||||
</li>
|
||||
<li>
|
||||
The protected factory is described in
|
||||
<a href="http://www-106.ibm.com/developerworks/java/library/j-mocktest.html">this paper from IBM</a>.
|
||||
This is the only formal comment I have seen on this problem.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<span class="chosen">Partial mocks</span>
|
||||
|
|
||||
<a href="reporter_documentation.html">Reporting</a>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,616 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>SimpleTest for PHP test runner and display documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
|
||||
</head>
|
||||
<body>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<span class="chosen">Reporting</span>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<h1>Test reporter documentation</h1>
|
||||
This page...
|
||||
<ul>
|
||||
<li>
|
||||
Displaying <a href="#html">results in HTML</a>
|
||||
</li>
|
||||
<li>
|
||||
Displaying and <a href="#other">reporting results</a>
|
||||
in other formats
|
||||
</li>
|
||||
<li>
|
||||
Using <a href="#cli">SimpleTest from the command line</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#xml">Using XML</a> for remote testing
|
||||
</li>
|
||||
</ul>
|
||||
<div class="content">
|
||||
|
||||
<p>
|
||||
SimpleTest pretty much follows the MVC-ish pattern
|
||||
(Model-View-Controller).
|
||||
The reporter classes are the view and the model is your
|
||||
test cases and their hiearchy.
|
||||
The controller is mostly hidden from the user of
|
||||
SimpleTest unless you want to change how the test cases
|
||||
are actually run, in which case it is possible to
|
||||
override the runner objects from within the test case.
|
||||
As usual with MVC, the controller is mostly undefined
|
||||
and there are other places to control the test run.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="html"></a>Reporting results in HTML</h2>
|
||||
<p>
|
||||
The default HTML display is minimal in the extreme.
|
||||
It reports success and failure with the conventional red and
|
||||
green bars and shows a breadcrumb trail of test groups
|
||||
for every failed assertion.
|
||||
Here's a fail...
|
||||
<div class="demo">
|
||||
<h1>File test</h1>
|
||||
<span class="fail">Fail</span>: createnewfile->True assertion failed.<br>
|
||||
<div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
|
||||
<strong>0</strong> passes, <strong>1</strong> fails and <strong>0</strong> exceptions.</div>
|
||||
</div>
|
||||
And here all tests passed...
|
||||
<div class="demo">
|
||||
<h1>File test</h1>
|
||||
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
||||
<strong>1</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
|
||||
</div>
|
||||
The good news is that there are several points in the display
|
||||
hiearchy for subclassing.
|
||||
</p>
|
||||
<p>
|
||||
For web page based displays there is the
|
||||
<span class="new_code">HtmlReporter</span> class with the following
|
||||
signature...
|
||||
<pre>
|
||||
class HtmlReporter extends SimpleReporter {
|
||||
public __construct($encoding) { ... }
|
||||
public makeDry(boolean $is_dry) { ... }
|
||||
public void paintHeader(string $test_name) { ... }
|
||||
public void sendNoCacheHeaders() { ... }
|
||||
public void paintFooter(string $test_name) { ... }
|
||||
public void paintGroupStart(string $test_name, integer $size) { ... }
|
||||
public void paintGroupEnd(string $test_name) { ... }
|
||||
public void paintCaseStart(string $test_name) { ... }
|
||||
public void paintCaseEnd(string $test_name) { ... }
|
||||
public void paintMethodStart(string $test_name) { ... }
|
||||
public void paintMethodEnd(string $test_name) { ... }
|
||||
public void paintFail(string $message) { ... }
|
||||
public void paintPass(string $message) { ... }
|
||||
public void paintError(string $message) { ... }
|
||||
public void paintException(string $message) { ... }
|
||||
public void paintMessage(string $message) { ... }
|
||||
public void paintFormattedMessage(string $message) { ... }
|
||||
protected string getCss() { ... }
|
||||
public array getTestList() { ... }
|
||||
public integer getPassCount() { ... }
|
||||
public integer getFailCount() { ... }
|
||||
public integer getExceptionCount() { ... }
|
||||
public integer getTestCaseCount() { ... }
|
||||
public integer getTestCaseProgress() { ... }
|
||||
}
|
||||
</pre>
|
||||
Here is what some of these methods mean. First the display methods
|
||||
that you will probably want to override...
|
||||
<ul class="api">
|
||||
<li>
|
||||
<span class="new_code">HtmlReporter(string $encoding)</span><br>
|
||||
is the constructor.
|
||||
Note that the unit test sets up the link to the display
|
||||
rather than the other way around.
|
||||
The display is a mostly passive receiver of test events.
|
||||
This allows easy adaption of the display for other test
|
||||
systems beside unit tests, such as monitoring servers.
|
||||
The encoding is the character encoding you wish to
|
||||
display the test output in.
|
||||
In order to correctly render debug output when
|
||||
using the web tester, this should match the encoding
|
||||
of the site you are trying to test.
|
||||
The available character set strings are described in
|
||||
the PHP <a href="http://www.php.net/manual/en/function.htmlentities.php">html_entities()</a>
|
||||
function.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintHeader(string $test_name)</span><br>
|
||||
is called once at the very start of the test when the first
|
||||
start event arrives.
|
||||
The first start event is usually delivered by the top level group
|
||||
test and so this is where <span class="new_code">$test_name</span>
|
||||
comes from.
|
||||
It paints the page title, CSS, body tag, etc.
|
||||
It returns nothing (<span class="new_code">void</span>).
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintFooter(string $test_name)</span><br>
|
||||
Called at the very end of the test to close any tags opened
|
||||
by the page header.
|
||||
By default it also displays the red/green bar and the final
|
||||
count of results.
|
||||
Actually the end of the test happens when a test end event
|
||||
comes in with the same name as the one that started it all
|
||||
at the same level.
|
||||
The tests nest you see.
|
||||
Closing the last test finishes the display.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintMethodStart(string $test_name)</span><br>
|
||||
is called at the start of each test method.
|
||||
The name normally comes from method name.
|
||||
The other test start events behave the same way except
|
||||
that the group test one tells the reporter how large
|
||||
it is in number of held test cases.
|
||||
This is so that the reporter can display a progress bar
|
||||
as the runner churns through the test cases.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintMethodEnd(string $test_name)</span><br>
|
||||
backs out of the test started with the same name.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintFail(string $message)</span><br>
|
||||
paints a failure.
|
||||
By default it just displays the word fail, a breadcrumbs trail
|
||||
showing the current test nesting and the message issued by
|
||||
the assertion.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">void paintPass(string $message)</span><br>
|
||||
by default does nothing.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">string getCss()</span><br>
|
||||
Returns the CSS styles as a string for the page header
|
||||
method.
|
||||
Additional styles have to be appended here if you are
|
||||
not overriding the page header.
|
||||
You will want to use this method in an overriden page header
|
||||
if you want to include the original CSS.
|
||||
</li>
|
||||
</ul>
|
||||
There are also some accessors to get information on the current
|
||||
state of the test suite.
|
||||
Use these to enrich the display...
|
||||
<ul class="api">
|
||||
<li>
|
||||
<span class="new_code">array getTestList()</span><br>
|
||||
is the first convenience method for subclasses.
|
||||
Lists the current nesting of the tests as a list
|
||||
of test names.
|
||||
The first, top level test case, is first in the
|
||||
list and the current test method will be last.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">integer getPassCount()</span><br>
|
||||
returns the number of passes chalked up so far.
|
||||
Needed for the display at the end.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">integer getFailCount()</span><br>
|
||||
is likewise the number of fails so far.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">integer getExceptionCount()</span><br>
|
||||
is likewise the number of errors so far.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">integer getTestCaseCount()</span><br>
|
||||
is the total number of test cases in the test run.
|
||||
This includes the grouping tests themselves.
|
||||
</li>
|
||||
<li>
|
||||
<span class="new_code">integer getTestCaseProgress()</span><br>
|
||||
is the number of test cases completed so far.
|
||||
</li>
|
||||
</ul>
|
||||
One simple modification is to get the HtmlReporter to display
|
||||
the passes as well as the failures and errors...
|
||||
<pre>
|
||||
<strong>class ReporterShowingPasses extends HtmlReporter {
|
||||
|
||||
function paintPass($message) {
|
||||
parent::paintPass($message);
|
||||
print "<span class=\"pass\">Pass</span>: ";
|
||||
$breadcrumb = $this->getTestList();
|
||||
array_shift($breadcrumb);
|
||||
print implode("-&gt;", $breadcrumb);
|
||||
print "-&gt;$message<br />\n";
|
||||
}
|
||||
|
||||
protected function getCss() {
|
||||
return parent::getCss() . ' .pass { color: green; }';
|
||||
}
|
||||
}</strong>
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
One method that was glossed over was the <span class="new_code">makeDry()</span>
|
||||
method.
|
||||
If you run this method, with no parameters, on the reporter
|
||||
before the test suite is run no actual test methods
|
||||
will be called.
|
||||
You will still get the events of entering and leaving the
|
||||
test methods and test cases, but no passes or failures etc,
|
||||
because the test code will not actually be executed.
|
||||
</p>
|
||||
<p>
|
||||
The reason for this is to allow for more sophistcated
|
||||
GUI displays that allow the selection of individual test
|
||||
cases.
|
||||
In order to build a list of possible tests they need a
|
||||
report on the test structure for drawing, say a tree view
|
||||
of the test suite.
|
||||
With a reporter set to dry run that just sends drawing events
|
||||
this is easily accomplished.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="other"></a>Extending the reporter</h2>
|
||||
<p>
|
||||
Rather than simply modifying the existing display, you might want to
|
||||
produce a whole new HTML look, or even generate text or XML.
|
||||
Rather than override every method in
|
||||
<span class="new_code">HtmlReporter</span> we can take one
|
||||
step up the class hiearchy to <span class="new_code">SimpleReporter</span>
|
||||
in the <em>simple_test.php</em> source file.
|
||||
</p>
|
||||
<p>
|
||||
A do nothing display, a blank canvas for your own creation, would
|
||||
be...
|
||||
<pre>
|
||||
<strong>require_once('simpletest/simpletest.php');</strong>
|
||||
|
||||
class MyDisplay extends SimpleReporter {<strong>
|
||||
</strong>
|
||||
function paintHeader($test_name) { }
|
||||
|
||||
function paintFooter($test_name) { }
|
||||
|
||||
function paintStart($test_name, $size) {<strong>
|
||||
parent::paintStart($test_name, $size);</strong>
|
||||
}
|
||||
|
||||
function paintEnd($test_name, $size) {<strong>
|
||||
parent::paintEnd($test_name, $size);</strong>
|
||||
}
|
||||
|
||||
function paintPass($message) {<strong>
|
||||
parent::paintPass($message);</strong>
|
||||
}
|
||||
|
||||
function paintFail($message) {<strong>
|
||||
parent::paintFail($message);</strong>
|
||||
}
|
||||
|
||||
function paintError($message) {<strong>
|
||||
parent::paintError($message);</strong>
|
||||
}
|
||||
|
||||
function paintException($exception) {<strong>
|
||||
parent::paintException($exception);</strong>
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
No output would come from this class until you add it.
|
||||
</p>
|
||||
<p>
|
||||
The catch with using this low level class is that you must
|
||||
explicitely invoke it in the test script.
|
||||
The "autorun" facility will not be able to use
|
||||
its runtime context (whether it's running in a web browser
|
||||
or the command line) to select the reporter.
|
||||
</p>
|
||||
<p>
|
||||
You explicitely invoke the test runner like so...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
$test = new TestSuite('File test');
|
||||
$test->addFile('tests/file_test.php');
|
||||
$test->run(<strong>new MyReporter()</strong>);
|
||||
?>
|
||||
</pre>
|
||||
...perhaps like this...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/simpletest.php');
|
||||
require_once('my_reporter.php');
|
||||
|
||||
class MyTest extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addFile('tests/file_test.php');
|
||||
}
|
||||
}
|
||||
|
||||
$test = new MyTest();
|
||||
$test->run(<strong>new MyReporter()</strong>);
|
||||
?>
|
||||
</pre>
|
||||
We'll show how to fit in with "autorun" later.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="cli"></a>The command line reporter</h2>
|
||||
<p>
|
||||
SimpleTest also ships with a minimal command line reporter.
|
||||
The interface mimics JUnit to some extent, but paints the
|
||||
failure messages as they arrive.
|
||||
To use the command line reporter explicitely, substitute it
|
||||
for the HTML version...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
$test = new TestSuite('File test');
|
||||
$test->addFile('tests/file_test.php');
|
||||
$test->run(<strong>new TextReporter()</strong>);
|
||||
?>
|
||||
</pre>
|
||||
Then invoke the test suite from the command line...
|
||||
<pre class="shell">
|
||||
php file_test.php
|
||||
</pre>
|
||||
You will need the command line version of PHP installed
|
||||
of course.
|
||||
A passing test suite looks like this...
|
||||
<pre class="shell">
|
||||
File test
|
||||
OK
|
||||
Test cases run: 1/1, Passes: 1, Failures: 0, Exceptions: 0
|
||||
</pre>
|
||||
A failure triggers a display like this...
|
||||
<pre class="shell">
|
||||
File test
|
||||
1) True assertion failed.
|
||||
in createNewFile
|
||||
FAILURES!!!
|
||||
Test cases run: 1/1, Passes: 0, Failures: 1, Exceptions: 0
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
One of the main reasons for using a command line driven
|
||||
test suite is of using the tester as part of some automated
|
||||
process.
|
||||
To function properly in shell scripts the test script should
|
||||
return a non-zero exit code on failure.
|
||||
If a test suite fails the value <span class="new_code">false</span>
|
||||
is returned from the <span class="new_code">SimpleTest::run()</span>
|
||||
method.
|
||||
We can use that result to exit the script with the desired return
|
||||
code...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
$test = new TestSuite('File test');
|
||||
$test->addFile('tests/file_test.php');
|
||||
<strong>exit ($test->run(new TextReporter()) ? 0 : 1);</strong>
|
||||
?>
|
||||
</pre>
|
||||
Of course we wouldn't really want to create two test scripts,
|
||||
a command line one and a web browser one, for each test suite.
|
||||
The command line reporter includes a method to sniff out the
|
||||
run time environment...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
$test = new TestSuite('File test');
|
||||
$test->addFile('tests/file_test.php');
|
||||
<strong>if (TextReporter::inCli()) {</strong>
|
||||
exit ($test->run(new TextReporter()) ? 0 : 1);
|
||||
<strong>}</strong>
|
||||
$test->run(new HtmlReporter());
|
||||
?>
|
||||
</pre>
|
||||
This is the form used within SimpleTest itself.
|
||||
When you use the "autorun.php", and no
|
||||
test has been run by the end, this is pretty much
|
||||
the code that SimpleTest will run for you implicitely.
|
||||
</p>
|
||||
<p>
|
||||
In other words, this is gives the same result...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
class MyTest extends TestSuite {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->addFile('tests/file_test.php');
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<a class="target" name="xml"></a>Remote testing</h2>
|
||||
<p>
|
||||
SimpleTest ships with an <span class="new_code">XmlReporter</span> class
|
||||
used for internal communication.
|
||||
When run the output looks like...
|
||||
<pre class="shell">
|
||||
<?xml version="1.0"?>
|
||||
<run>
|
||||
<group size="4">
|
||||
<name>Remote tests</name>
|
||||
<group size="4">
|
||||
<name>Visual test with 48 passes, 48 fails and 4 exceptions</name>
|
||||
<case>
|
||||
<name>testofunittestcaseoutput</name>
|
||||
<test>
|
||||
<name>testofresults</name>
|
||||
<pass>This assertion passed</pass>
|
||||
<fail>This assertion failed</fail>
|
||||
</test>
|
||||
<test>
|
||||
...
|
||||
</test>
|
||||
</case>
|
||||
</group>
|
||||
</group>
|
||||
</run>
|
||||
</pre>
|
||||
To get your normal test cases to produce this format, on the
|
||||
command line add the <span class="new_code">--xml</span> flag.
|
||||
<pre class="shell">
|
||||
php my_test.php --xml
|
||||
</pre>
|
||||
You can do teh same thing in the web browser by adding the
|
||||
URL parameter <span class="new_code">xml=1</span>.
|
||||
Any true value will do.
|
||||
</p>
|
||||
<p>
|
||||
You can consume this format with the parser
|
||||
supplied as part of SimpleTest itself.
|
||||
This is called <span class="new_code">SimpleTestXmlParser</span> and
|
||||
resides in <em>xml.php</em> within the SimpleTest package...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/xml.php');
|
||||
|
||||
...
|
||||
$parser = new SimpleTestXmlParser(new HtmlReporter());
|
||||
$parser->parse($test_output);
|
||||
?>
|
||||
</pre>
|
||||
The <span class="new_code">$test_output</span> should be the XML format
|
||||
from the XML reporter, and could come from say a command
|
||||
line run of a test case.
|
||||
The parser sends events to the reporter just like any
|
||||
other test run.
|
||||
There are some odd occasions where this is actually useful.
|
||||
</p>
|
||||
<p>
|
||||
Most likely it's when you want to isolate a problematic crash
|
||||
prone test.
|
||||
You can collect the XML output using the backtick operator
|
||||
from another test.
|
||||
In that way it runs in its own process...
|
||||
<pre>
|
||||
<?php
|
||||
require_once('simpletest/xml.php');
|
||||
|
||||
if (TextReporter::inCli()) {
|
||||
$parser = new SimpleTestXmlParser(new TextReporter());
|
||||
} else {
|
||||
$parser = new SimpleTestXmlParser(new HtmlReporter());
|
||||
}
|
||||
$parser->parse(`php flakey_test.php --xml`);
|
||||
?>
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
Another use is breaking up large test suites.
|
||||
</p>
|
||||
<p>
|
||||
A problem with large test suites is thet they can exhaust
|
||||
the default 16Mb memory limit on a PHP process.
|
||||
By having the test groups output in XML and run in
|
||||
separate processes, the output can be reparsed to
|
||||
aggregate the results into a much smaller footprint top level
|
||||
test.
|
||||
</p>
|
||||
<p>
|
||||
Because the XML output can come from anywhere, this opens
|
||||
up the possibility of aggregating test runs from remote
|
||||
servers.
|
||||
A test case already exists to do this within the SimpleTest
|
||||
framework, but it is currently experimental...
|
||||
<pre>
|
||||
<?php
|
||||
<strong>require_once('../remote.php');</strong>
|
||||
require_once('simpletest/autorun.php');
|
||||
|
||||
$test_url = ...;
|
||||
$dry_url = ...;
|
||||
|
||||
class MyTestOnAnotherServer extends RemoteTestCase {
|
||||
function __construct() {
|
||||
$test_url = ...
|
||||
parent::__construct($test_url, $test_url . ' --dry');
|
||||
}
|
||||
}
|
||||
?>
|
||||
</pre>
|
||||
The <span class="new_code">RemoteTestCase</span> takes the actual location
|
||||
of the test runner, basically a web page in XML format.
|
||||
It also takes the URL of a reporter set to do a dry run.
|
||||
This is so that progress can be reported upward correctly.
|
||||
The <span class="new_code">RemoteTestCase</span> can be added to test suites
|
||||
just like any other test suite.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
References and related information...
|
||||
<ul>
|
||||
<li>
|
||||
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
||||
</li>
|
||||
<li>
|
||||
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
||||
</li>
|
||||
<li>
|
||||
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
||||
gives full detail on the classes and assertions available.
|
||||
</li>
|
||||
</ul>
|
||||
<div class="menu_back"><div class="menu">
|
||||
<a href="index.html">SimpleTest</a>
|
||||
|
|
||||
<a href="overview.html">Overview</a>
|
||||
|
|
||||
<a href="unit_test_documentation.html">Unit tester</a>
|
||||
|
|
||||
<a href="group_test_documentation.html">Group tests</a>
|
||||
|
|
||||
<a href="mock_objects_documentation.html">Mock objects</a>
|
||||
|
|
||||
<a href="partial_mocks_documentation.html">Partial mocks</a>
|
||||
|
|
||||
<span class="chosen">Reporting</span>
|
||||
|
|
||||
<a href="expectation_documentation.html">Expectations</a>
|
||||
|
|
||||
<a href="web_tester_documentation.html">Web tester</a>
|
||||
|
|
||||
<a href="form_testing_documentation.html">Testing forms</a>
|
||||
|
|
||||
<a href="authentication_documentation.html">Authentication</a>
|
||||
|
|
||||
<a href="browser_documentation.html">Scriptable browser</a>
|
||||
</div></div>
|
||||
<div class="copyright">
|
||||
Copyright<br>Marcus Baker 2006
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user