├── README.markdown
├── mongo.css
├── mongoDB_Banner.png
└── mongodbadmin.php
/README.markdown:
--------------------------------------------------------------------------------
1 | # PHP MongoDB Admin
2 |
3 | ## THIS REPOSITORY IS NO LONGER ACTIVELY MAINTAINED OR SUPPORTED
4 |
5 | A MongoDB Admin interface that runs in your web browser.
6 |
7 | Open mongodbadmin.php in your browser and have a look!
8 |
--------------------------------------------------------------------------------
/mongo.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | /* CSS Document */
3 |
4 | html{color:#000;background:#FFF;}
5 | body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;color:#666;}
6 | table{border-collapse:collapse;border-spacing:0;}
7 | fieldset,img{border:0;}
8 | address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}
9 | li{list-style:none;}
10 | caption,th{text-align:left;}
11 | h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
12 | q:before,q:after{content:'';}
13 | abbr,acronym{border:0;font-variant:normal;}
14 | sup{vertical-align:text-top;}
15 | sub{vertical-align:text-bottom;}
16 | input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}
17 | input,textarea,select{*font-size:100%;}
18 | legend{color:#000;}
19 | html { background: #666; font:13px/1.231 "Lucida Grande",verdana,arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}
20 | table {font-size:inherit;font:100%;}
21 | pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
22 | a:link, a:visited, a:active { text-decoration:none; color:#666; outline:none; border:0; }
23 | a:hover { color:#F90; text-decoration:none; border:0; }
24 |
25 | pre {
26 | -moz-border-radius: 10px;
27 | -webkit-border-radius: 10px;
28 | border-radius: 10px;
29 | padding: 10px;
30 | background-color: #222;
31 | overflow/**/: auto;
32 | margin-bottom: 15px;
33 | line-height: 17px;
34 | font-size: 13px;
35 | color: #fff;
36 | font-family: "Bitstream Vera Sans Mono", monospace;
37 | white-space: pre-wrap;
38 | }
39 |
40 | pre a {
41 | color: #fff !important;
42 | text-decoration: underline !important;
43 | }
44 |
45 | #content {
46 | -moz-border-radius: 10px;
47 | -webkit-border-radius: 10px;
48 | border-radius: 10px;
49 | margin-top: 20px;
50 | margin-bottom: 20px;
51 | padding: 20px;
52 | width: 90%;
53 | margin-left: auto;
54 | margin-right: auto;
55 | position:relative;
56 | background:#FFF;
57 | color: #495a7e;
58 | }
59 | #content h1 { font-size: 20px; font-weight: bold; margin-bottom: 15px; color:#FBDDA4; }
60 | #content h2 { font-size: 14px; font-weight: bold; margin-bottom: 15px; margin-top: 10px; color:#5AAC41; }
61 |
62 | #footer {
63 | margin-top: 15px;
64 | text-align: center;
65 | font-weight: bold;
66 | font-size: 10px;
67 | color:#FFF;
68 | }
69 |
70 | #create_form {
71 | -moz-border-radius: 10px;
72 | -webkit-border-radius: 10px;
73 | border-radius: 10px;
74 | padding: 15px;
75 | background: #5AAC41;
76 | width: 400px;
77 | float: right;
78 | margin-bottom: 10px;
79 | }
80 | #create_form label {
81 | float: left;
82 | padding: 4px;
83 | font-weight: bold;
84 | margin-right: 10px;
85 | color:#FFF;
86 | }
87 | #pager {
88 | -moz-border-radius: 10px;
89 | -webkit-border-radius: 10px;
90 | border-radius: 10px;
91 | background: #f5f5f5;
92 | padding: 8px;
93 | margin-bottom: 15px;
94 | width: 350px;
95 | float: left;
96 | }
97 | #search {
98 | -moz-border-radius: 10px;
99 | -webkit-border-radius: 10px;
100 | border-radius: 10px;
101 | background: #F90;
102 | padding: 8px;
103 | margin-bottom: 15px;
104 | width: 500px;
105 | float: right;
106 | }
107 | #mongoLogo{
108 | background-image:url(mongoDB_Banner.png);
109 | background-repeat:no-repeat;
110 | width:200px;
111 | height:75px;
112 | float:left;
113 | margin-left:-32px;
114 | }
115 | table {
116 | background: #000;
117 | -moz-border-radius: 10px;
118 | -webkit-border-radius: 10px;
119 | border-radius: 10px;
120 | border-collapse: collapse;
121 | width: 100%;
122 | }
123 | table th {
124 | color: #fff;
125 | font-weight: bold;
126 | padding: 8px;
127 | }
128 | table td {
129 | padding: 8px;
130 | }
131 | table td a {
132 | font-weight: bold;
133 | }
134 | table tbody tr {
135 | background-color: #F3F4EB;
136 | border-bottom: 1px solid #ccc;
137 | }
138 | table tbody tr:hover {
139 | background-color: #333;
140 | }
141 | .save_button {
142 | -moz-border-radius: 10px;
143 | -webkit-border-radius: 10px;
144 | border-radius: 10px;
145 | background-color: #F90;
146 | color: #fff;
147 | padding: 4px;
148 | font-weight: bold;
149 | padding-left: 10px;
150 | padding-right: 10px;
151 | }
152 | .save_button:hover {
153 | background-color: #ccc;
154 | color: #333;
155 | cursor: pointer;
156 | }
157 | textarea {
158 | padding: 10px;
159 | -moz-border-radius: 10px;
160 | -webkit-border-radius: 10px;
161 | border-radius: 10px;
162 | border: 1px solid #ccc;
163 | width: 100%;
164 | height: 350px;
165 | margin-top: 10px;
166 | margin-bottom: 10px;
167 | }
168 | .footer{color:#CCC;}
--------------------------------------------------------------------------------
/mongoDB_Banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwage/php-mongodb-admin/2f3b703db24754d4045941c88d297493f83d3b57/mongoDB_Banner.png
--------------------------------------------------------------------------------
/mongodbadmin.php:
--------------------------------------------------------------------------------
1 |
18 | * @Theme Ted Veatch
19 | */
20 |
21 | header('Pragma: no-cache');
22 |
23 | $server = array(
24 | 'mongodb://localhost:27017',
25 | // 'mongodb://example.org:27017',
26 | );
27 |
28 | $options = array(
29 | 'connect' => true
30 | );
31 |
32 | $readOnly = false;
33 |
34 | if (!class_exists('MongoClient'))
35 | {
36 | die("Mongo support required. Install mongo pecl extension with 'pecl install mongo; echo \"extension=mongo.so\" >> php.ini'");
37 | }
38 | try
39 | {
40 | $mongo = new MongoClient(getServer($server), $options);
41 | }
42 | catch (MongoConnectionException $ex)
43 | {
44 | error_log($ex->getMessage());
45 | die("Failed to connect to MongoDB");
46 | }
47 |
48 |
49 | /**
50 | * Get the current MongoDB server.
51 | *
52 | * @param mixed $server
53 | * @return string $server
54 | */
55 | function getServer($server)
56 | {
57 | if (is_array($server)) {
58 | return (isset($_COOKIE['mongo_server']) && isset($server[$_COOKIE['mongo_server']])) ? $server[$_COOKIE['mongo_server']] : $server[0];
59 | } else {
60 | return $server;
61 | }
62 | }
63 |
64 | /**
65 | * Render a document preview for the black code box with referenced
66 | * linked to the collection and id for that database reference.
67 | *
68 | * @param string $document
69 | * @return string $preview
70 | */
71 | function renderDocumentPreview($mongo, $document)
72 | {
73 | $document = prepareMongoDBDocumentForEdit($document);
74 | $preview = linkDocumentReferences($mongo, $document);
75 | $preview = print_r($preview, true);
76 | return $preview;
77 | }
78 |
79 | /**
80 | * Change any references to other documents to include a html link
81 | * to that document and collection. Used by the renderDocumentPreview() function.
82 | *
83 | * @param array $document
84 | * @return array $document
85 | */
86 | function linkDocumentReferences($mongo, $document)
87 | {
88 | foreach ($document as $key => $value) {
89 | if (is_array($value)) {
90 | if (isset($value['$ref'])) {
91 | $collection = $mongo->selectDB($_REQUEST['db'])->selectCollection($value['$ref']);
92 | $id = $value['$id'];
93 |
94 | $ref = findMongoDbDocument($value['$id'], $_REQUEST['db'], $value['$ref']);
95 | if (!$ref) {
96 | $ref = findMongoDbDocument($value['$id'], $_REQUEST['db'], $value['$ref'], true);
97 | }
98 |
99 | $refDb = isset($value['$db']) ? $value['$db'] : $_REQUEST['db'];
100 |
101 | $document[$key]['$ref'] = ''.$value['$ref'].'';
102 |
103 | if ($ref['_id'] instanceof MongoId) {
104 | $document[$key]['$id'] = ''.$value['$id'].'';
105 | } else {
106 | $document[$key]['$id'] = ''.$value['$id'].'';
107 | }
108 |
109 | if (isset($value['$db'])) {
110 | $document[$key]['$db'] = ''.$refDb.'';
111 | }
112 | } else {
113 | $document[$key] = linkDocumentReferences($mongo, $value);
114 | }
115 | }
116 | }
117 | return $document;
118 | }
119 |
120 | /**
121 | * Prepare user submitted array of PHP code as a MongoDB
122 | * document that can be saved.
123 | *
124 | * @param mixed $value
125 | * @return array $document
126 | */
127 | function prepareValueForMongoDB($value)
128 | {
129 | $customId = isset($_REQUEST['custom_id']);
130 |
131 | if (is_string($value)) {
132 | $value = preg_replace('/\'_id\' => \s*MongoId::__set_state\(array\(\s*\)\)/', '\'_id\' => new MongoId("' . (isset($_REQUEST['id']) ? $_REQUEST['id'] : '') . '")', $value);
133 | $value = preg_replace('/MongoId::__set_state\(array\(\s*\)\)/', 'new MongoId()', $value);
134 | $value = preg_replace('/MongoDate::__set_state\(array\(\s*\'sec\' => (\d+),\s*\'usec\' => \d+,\s*\)\)/m', 'new MongoDate($1)', $value);
135 | $value = preg_replace('/MongoBinData::__set_state\(array\(\s*\'bin\' => \'(.*?)\',\s*\'type\' => ([1,2,3,5,128]),\s*\)\)/m', 'new MongoBinData(\'$1\', $2)', $value);
136 |
137 | eval('$value = ' . $value . ';');
138 |
139 | if (!$value) {
140 | header('location: ' . $_SERVER['HTTP_REFERER'] . ($customId ? '&custom_id=1' : null));
141 | exit;
142 | }
143 | }
144 |
145 | $prepared = array();
146 | foreach ($value as $k => $v) {
147 | if ($k === '_id' && !$customId) {
148 | $v = new MongoId($v);
149 | }
150 |
151 | if ($k === '$id' && !$customId) {
152 | $v = new MongoId($v);
153 | }
154 |
155 | if (is_array($v)) {
156 | $prepared[$k] = prepareValueForMongoDB($v);
157 | } else {
158 | $prepared[$k] = mysqli_real_escape_string($v);
159 | }
160 | }
161 | return $prepared;
162 | }
163 |
164 | /**
165 | * Prepare a MongoDB document for the textarea so it can be edited.
166 | *
167 | * @param array $value
168 | * @return array $prepared
169 | */
170 | function prepareMongoDBDocumentForEdit($value)
171 | {
172 | $prepared = array();
173 | foreach ($value as $key => $value) {
174 | if ($key === '_id') {
175 | $value = (string) $value;
176 | }
177 | if ($key === '$id') {
178 | $value = (string) $value;
179 | }
180 | if (is_array($value)) {
181 | $prepared[$key] = prepareMongoDBDocumentForEdit($value);
182 | } else {
183 | $prepared[$key] = $value;
184 | }
185 | }
186 | return $prepared;
187 | }
188 |
189 | /**
190 | * Search for a MongoDB document based on the id
191 | *
192 | * @param string $id The ID to search for
193 | * @param string $db The db to use
194 | * @param string $collection The collection to search in
195 | * @param bool $forceCustomId True to force a custom id search
196 | * @return mixed $document
197 | *
198 | */
199 | function findMongoDbDocument($id, $db, $collection, $forceCustomId = false)
200 | {
201 | global $mongo;
202 |
203 | $collection = $mongo->selectDB($db)->selectCollection($collection);
204 |
205 | if (isset($_REQUEST['custom_id']) || $forceCustomId) {
206 | if (is_numeric($id)) {
207 | $id = (int) $id;
208 | }
209 | $document =$collection->findOne(array('_id' => $id));
210 | } else {
211 | $document = $collection->findOne(array('_id' => new MongoId($id)));
212 | }
213 |
214 | return $document;
215 | }
216 |
217 | // Actions
218 | try {
219 | // SEARCH BY ID
220 | if (isset($_REQUEST['search']) && !is_object(json_decode($_REQUEST['search']))) {
221 | $customId = false;
222 | $document = findMongoDbDocument($_REQUEST['search'], $_REQUEST['db'], $_REQUEST['collection']);
223 |
224 | if (!$document) {
225 | $document = findMongoDbDocument($_REQUEST['search'], $_REQUEST['db'], $_REQUEST['collection'], true);
226 | $customId = true;
227 | }
228 |
229 | if (isset($document['_id'])) {
230 | $url = $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']) . '&collection=' . $_REQUEST['collection'] . '&id=' . (string) $document['_id'];
231 |
232 | if ($customId) {
233 | header('location: ' . $url . '&custom_id=true');
234 | } else {
235 | header('location: ' . $url);
236 | }
237 | }
238 | }
239 |
240 | // DELETE DB
241 | if (isset($_REQUEST['delete_db']) && $readOnly !== true) {
242 | $mongo
243 | ->selectDB($_REQUEST['delete_db'])
244 | ->drop();
245 |
246 | header('location: ' . $_SERVER['PHP_SELF']);
247 | exit;
248 | }
249 |
250 | // CREATE DB
251 | if (isset($_REQUEST['create_db']) && $readOnly !== true) {
252 | $mongo->selectDB($_REQUEST['create_db'])->createCollection('__tmp_collection_');
253 | $mongo->selectDB($_REQUEST['create_db'])->dropCollection('__tmp_collection_');
254 |
255 | header('location: ' . $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['create_db']));
256 | exit;
257 |
258 | }
259 |
260 | // CREATE DB COLLECTION
261 | if (isset($_REQUEST['create_collection']) && $readOnly !== true) {
262 | $mongo
263 | ->selectDB($_REQUEST['db'])
264 | ->createCollection($_REQUEST['create_collection']);
265 |
266 | header('location: ' . $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']) . '&collection=' . $_REQUEST['create_collection']);
267 | exit;
268 | }
269 |
270 | // DELETE DB COLLECTION
271 | if (isset($_REQUEST['delete_collection']) && $readOnly !== true) {
272 | $mongo
273 | ->selectDB($_REQUEST['db'])
274 | ->selectCollection($_REQUEST['delete_collection'])
275 | ->drop();
276 |
277 | header('location: ' . $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']));
278 | exit;
279 | }
280 |
281 | // DELETE DB COLLECTION DOCUMENT
282 | if (isset($_REQUEST['delete_document']) && $readOnly !== true) {
283 | $collection = $mongo->selectDB($_REQUEST['db'])->selectCollection($_REQUEST['collection']);
284 |
285 | if (isset($_REQUEST['custom_id'])) {
286 | $id = $_REQUEST['delete_document'];
287 | if (is_numeric($id)) {
288 | $id = (int) $id;
289 | }
290 | $collection->remove(array('_id' => $id));
291 | } else {
292 | $collection->remove(array('_id' => new MongoId($_REQUEST['delete_document'])));
293 | }
294 |
295 | header('location: ' . $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']) . '&collection=' . $_REQUEST['collection']);
296 | exit;
297 | }
298 |
299 | // DELETE DB COLLECTION DOCUMENT FIELD AND VALUE
300 | if (isset($_REQUEST['delete_document_field']) && $readOnly !== true) {
301 | $coll = $mongo
302 | ->selectDB($_REQUEST['db'])
303 | ->selectCollection($_REQUEST['collection']);
304 |
305 | $document = findMongoDbDocument($_REQUEST['id'], $_REQUEST['db'], $_REQUEST['collection']);
306 | unset($document[$_REQUEST['delete_document_field']]);
307 | $coll->save($document);
308 |
309 | $url = $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']) . '&collection=' . $_REQUEST['collection'] . '&id=' . (string) $document['_id'];
310 | header('location: ' . $url);
311 | exit;
312 | }
313 |
314 | // INSERT OR UPDATE A DB COLLECTION DOCUMENT
315 | if (isset($_POST['save']) && $readOnly !== true) {
316 | $customId = isset($_REQUEST['custom_id']);
317 | $collection = $mongo->selectDB($_REQUEST['db'])->selectCollection($_REQUEST['collection']);
318 |
319 | $document = prepareValueForMongoDB($_REQUEST['value']);
320 | $collection->save($document);
321 |
322 | $url = $_SERVER['PHP_SELF'] . '?db=' . urlencode($_REQUEST['db']) . '&collection=' . $_REQUEST['collection'] . '&id=' . (string) $document['_id'];
323 | header('location: ' . $url . ($customId ? '&custom_id=1' : null));
324 | exit;
325 | }
326 |
327 | // Catch any errors and redirect to referrer with error
328 | } catch (Exception $e) {
329 | header('location: '.$_SERVER['HTTP_REFERER'].'&error='.htmlspecialchars($e->getMessage()));
330 | exit;
331 | }
332 | ?>
333 |
334 |
335 |
336 | PHP MongoDB Admin
337 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 | 1): ?>
369 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
399 |
400 |
401 |
402 |
Databases
403 |
404 |
405 |
406 |
407 | Name |
408 | Collections |
409 | |
410 |
411 |
412 |
413 | listDBs() ?>
414 |
415 |
416 | |
417 | selectDb($db['name'])->listCollections()) ?> |
418 |
419 |
420 | Delete |
421 |
422 | |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
439 |
440 |
441 |
442 |
443 | Databases >>
444 |
445 |
446 |
447 |
448 |
449 | Collection Name |
450 | Documents |
451 | |
452 |
453 |
454 |
455 | selectDB($_REQUEST['db'])->listCollections() ?>
456 |
457 |
458 | getName() ?> |
459 | count(); ?> |
460 |
461 |
462 | Delete |
463 |
464 | |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 | selectDB($_REQUEST['db'])
485 | ->selectCollection($_REQUEST['collection'])
486 | ->find($search)
487 | ->limit($limit)
488 | ->skip($skip);
489 | } else {
490 | $cursor = $mongo
491 | ->selectDB($_REQUEST['db'])
492 | ->selectCollection($_REQUEST['collection'])
493 | ->find()
494 | ->limit($limit)
495 | ->skip($skip)
496 | ->sort(array('_id' => 1));
497 | }
498 |
499 | $total = $cursor->count();
500 | $pages = ceil($total / $max);
501 |
502 | if ($pages && $page > $pages) {
503 | header('location: ' . $_SERVER['HTTP_REFERER']);
504 | exit;
505 | }
506 | ?>
507 |
508 |
509 | Databases >>
510 | >>
511 | (count() ?> Documents)
512 |
513 |
514 | 1): ?>
515 |
520 |
521 |
522 |
523 |
530 |
531 |
532 |
533 |
534 | ID |
535 |
536 |
537 |
538 |
539 |
540 | |
541 |
542 | |
543 |
544 |
545 | $searchQuery) {
552 | if ($fieldName != '_id' && $fieldName[0] != '$' && isset($document[$fieldName])) {
553 | $fieldValue = $document[$fieldName];
554 |
555 | if (!is_array($fieldValue) && !is_object($fieldValue)) {
556 | $displayValues[] = $fieldName . ': ' . substr(str_replace("\n", '', htmlspecialchars($fieldValue)), 0, 100);
557 | }
558 | }
559 | }
560 |
561 | echo implode(' - ', $displayValues);
562 | }
563 |
564 | if (!isset($displayValues) || !count($displayValues)) {
565 | foreach ($document as $fieldName => $fieldValue) {
566 | if ($fieldName != '_id' && !is_array($fieldValue) && !is_object($fieldValue)) {
567 | echo $fieldName . ': ' . substr(str_replace("\n", '', htmlspecialchars($fieldValue)), 0, 100);
568 | break;
569 | }
570 | }
571 | }
572 | ?>
573 | |
574 |
575 | Delete |
576 |
577 | Delete |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
602 |
603 |
604 |
605 |
606 |
607 |
608 | Databases >>
609 | >>
610 | >>
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
631 |
632 |
633 |
634 |
Delete
635 |
636 |
Delete
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
--------------------------------------------------------------------------------